Kea 2.5.8
base_network_parser.cc
Go to the documentation of this file.
1// Copyright (C) 2019-2024 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#include <util/triplet.h>
11#include <util/optional.h>
12#include <util/str.h>
13
14using namespace isc::data;
15using namespace isc::util;
16
17namespace isc {
18namespace dhcp {
19
20void
22 if (!config->contains("reservation-mode")) {
23 return;
24 }
25 if (config->contains("reservations-global") ||
26 config->contains("reservations-in-subnet") ||
27 config->contains("reservations-out-of-pool")) {
28 isc_throw(DhcpConfigError, "invalid use of both 'reservation-mode'"
29 " and one of 'reservations-global', 'reservations-in-subnet'"
30 " or 'reservations-out-of-pool' parameters");
31 }
32 std::string hr_mode = getString(config, "reservation-mode");
33 if ((hr_mode == "disabled") || (hr_mode == "off")) {
34 config->set("reservations-global", Element::create(false));
35 config->set("reservations-in-subnet", Element::create(false));
36 } else if (hr_mode == "out-of-pool") {
37 config->set("reservations-global", Element::create(false));
38 config->set("reservations-in-subnet", Element::create(true));
39 config->set("reservations-out-of-pool", Element::create(true));
40 } else if (hr_mode == "global") {
41 config->set("reservations-global", Element::create(true));
42 config->set("reservations-in-subnet", Element::create(false));
43 } else if (hr_mode == "all") {
44 config->set("reservations-global", Element::create(false));
45 config->set("reservations-in-subnet", Element::create(true));
46 config->set("reservations-out-of-pool", Element::create(false));
47 } else {
48 isc_throw(DhcpConfigError, "invalid reservation-mode parameter: '"
49 << hr_mode << "' ("
50 << getPosition("reservation-mode", config) << ")");
51 }
52 config->remove("reservation-mode");
53}
54
55void
57 if (!config->get(CfgGlobals::RESERVATION_MODE)) {
58 return;
59 }
60 if (config->get(CfgGlobals::RESERVATIONS_GLOBAL) ||
63 isc_throw(DhcpConfigError, "invalid use of both 'reservation-mode'"
64 " and one of 'reservations-global', 'reservations-in-subnet'"
65 " or 'reservations-out-of-pool' parameters");
66 }
67 std::string hr_mode = config->get(CfgGlobals::RESERVATION_MODE)->stringValue();
68 if ((hr_mode == "disabled") || (hr_mode == "off")) {
71 } else if (hr_mode == "out-of-pool") {
75 } else if (hr_mode == "global") {
78 } else if (hr_mode == "all") {
81 config->set("reservations-out-of-pool", Element::create(false));
82 } else {
83 isc_throw(DhcpConfigError, "invalid reservation-mode parameter: '"
84 << hr_mode << "' ("
85 << config->get(CfgGlobals::RESERVATION_MODE)->getPosition()
86 << ")");
87 }
89}
90
91void
93 NetworkPtr& network) {
94 bool has_renew = network_data->contains("renew-timer");
95 bool has_rebind = network_data->contains("rebind-timer");
96 int64_t renew = -1;
97 int64_t rebind = -1;
98
99 if (has_renew) {
100 renew = getInteger(network_data, "renew-timer");
101 if (renew < 0) {
102 isc_throw(DhcpConfigError, "the value of renew-timer ("
103 << renew << ") must be a positive number");
104 }
105 network->setT1(renew);
106 }
107
108 if (has_rebind) {
109 rebind = getInteger(network_data, "rebind-timer");
110 if (rebind < 0) {
111 isc_throw(DhcpConfigError, "the value of rebind-timer ("
112 << rebind << ") must be a positive number");
113 }
114 network->setT2(rebind);
115 }
116
117 if (has_renew && has_rebind && (renew > rebind)) {
118 // The renew-timer value is too large and server logic
119 // later on will end up not sending it. Warn the user but
120 // allow the configuration to pass.
122 .arg(network->getLabel())
123 .arg(renew)
124 .arg(rebind);
125 }
126
127 network->setValid(parseIntTriplet(network_data, "valid-lifetime"));
128
129 if (network_data->contains("store-extended-info")) {
130 network->setStoreExtendedInfo(getBoolean(network_data,
131 "store-extended-info"));
132 }
133
134 if (network_data->contains("reservations-global")) {
135 network->setReservationsGlobal(getBoolean(network_data,
136 "reservations-global"));
137 }
138
139 if (network_data->contains("reservations-in-subnet")) {
140 network->setReservationsInSubnet(getBoolean(network_data,
141 "reservations-in-subnet"));
142 }
143
144 if (network_data->contains("reservations-out-of-pool")) {
145 network->setReservationsOutOfPool(getBoolean(network_data,
146 "reservations-out-of-pool"));
147 }
148}
149
150void
152 NetworkPtr& network) {
153 bool calculate_tee_times = network->getCalculateTeeTimes();
154 if (network_data->contains("calculate-tee-times")) {
155 calculate_tee_times = getBoolean(network_data, "calculate-tee-times");
156 network->setCalculateTeeTimes(calculate_tee_times);
157 }
158
159 Optional<double> t2_percent;
160 if (network_data->contains("t2-percent")) {
161 t2_percent = getDouble(network_data, "t2-percent");
162 }
163
164 Optional<double> t1_percent;
165 if (network_data->contains("t1-percent")) {
166 t1_percent = getDouble(network_data, "t1-percent");
167 }
168 if (calculate_tee_times) {
169 if (!t2_percent.unspecified() && ((t2_percent.get() <= 0.0) ||
170 (t2_percent.get() >= 1.0))) {
171 isc_throw(DhcpConfigError, "t2-percent: " << t2_percent.get()
172 << " is invalid, it must be greater than 0.0 and less than 1.0");
173 }
174
175 if (!t1_percent.unspecified() && ((t1_percent.get() <= 0.0) ||
176 (t1_percent.get() >= 1.0))) {
177 isc_throw(DhcpConfigError, "t1-percent: " << t1_percent.get()
178 << " is invalid it must be greater than 0.0 and less than 1.0");
179 }
180
181 if (!t1_percent.unspecified() && !t2_percent.unspecified() &&
182 (t1_percent.get() >= t2_percent.get())) {
183 isc_throw(DhcpConfigError, "t1-percent: " << t1_percent.get()
184 << " is invalid, it must be less than t2-percent: "
185 << t2_percent.get());
186 }
187 }
188
189 network->setT2Percent(t2_percent);
190 network->setT1Percent(t1_percent);
191}
192
193void
195 NetworkPtr& network) {
196 if (network_data->contains("cache-threshold")) {
197 double cache_threshold = getDouble(network_data, "cache-threshold");
198 if ((cache_threshold <= 0.0) || (cache_threshold >= 1.0)) {
199 isc_throw(DhcpConfigError, "cache-threshold: " << cache_threshold
200 << " is invalid, it must be greater than 0.0 and less than 1.0");
201 }
202 network->setCacheThreshold(cache_threshold);
203 }
204
205 if (network_data->contains("cache-max-age")) {
206 network->setCacheMaxAge(getInteger(network_data, "cache-max-age"));
207 }
208}
209
210void
212 NetworkPtr& network) {
213
214 if (network_data->contains("ddns-send-updates")) {
215 network->setDdnsSendUpdates(getBoolean(network_data, "ddns-send-updates"));
216 }
217
218 if (network_data->contains("ddns-override-no-update")) {
219 network->setDdnsOverrideNoUpdate(getBoolean(network_data, "ddns-override-no-update"));
220 }
221
222 if (network_data->contains("ddns-override-client-update")) {
223 network->setDdnsOverrideClientUpdate(getBoolean(network_data, "ddns-override-client-update"));
224 }
225
226 if (network_data->contains("ddns-replace-client-name")) {
227 network->setDdnsReplaceClientNameMode(getAndConvert<D2ClientConfig::ReplaceClientNameMode,
229 (network_data, "ddns-replace-client-name",
230 "ReplaceClientName mode"));
231 }
232
233 if (network_data->contains("ddns-generated-prefix")) {
234 network->setDdnsGeneratedPrefix(getString(network_data, "ddns-generated-prefix"));
235 }
236
237 if (network_data->contains("ddns-qualifying-suffix")) {
238 network->setDdnsQualifyingSuffix(getString(network_data, "ddns-qualifying-suffix"));
239 }
240
241 std::string hostname_char_set;
242 if (network_data->contains("hostname-char-set")) {
243 hostname_char_set = getString(network_data, "hostname-char-set");
244 network->setHostnameCharSet(hostname_char_set);
245 }
246
247 std::string hostname_char_replacement;
248 if (network_data->contains("hostname-char-replacement")) {
249 hostname_char_replacement = getString(network_data, "hostname-char-replacement");
250 network->setHostnameCharReplacement(hostname_char_replacement);
251 }
252
253 // We need to validate sanitizer values here so we can detect problems and
254 // cause a configuration. We don't retain the compilation because it's not
255 // something we can inherit.
256 if (!hostname_char_set.empty()) {
257 try {
258 str::StringSanitizerPtr sanitizer(new str::StringSanitizer(hostname_char_set,
259 hostname_char_replacement));
260 } catch (const std::exception& ex) {
261 isc_throw(BadValue, "hostname-char-set '" << hostname_char_set
262 << "' is not a valid regular expression");
263 }
264 }
265
266 if (network_data->contains("ddns-update-on-renew")) {
267 network->setDdnsUpdateOnRenew(getBoolean(network_data, "ddns-update-on-renew"));
268 }
269
270 if (network_data->contains("ddns-ttl-percent")) {
271 network->setDdnsTtlPercent(getDouble(network_data, "ddns-ttl-percent"));
272 }
273
274 // For backward compatibility, ddns-conflict-resolution-mode is optional.
275 if (network_data->contains("ddns-conflict-resolution-mode")) {
276 network->setDdnsConflictResolutionMode(getString(network_data,
277 "ddns-conflict-resolution-mode"));
278 }
279}
280
281void
283 NetworkPtr& network) {
284 if (network_data->contains("allocator")) {
285 auto allocator_type = getString(network_data, "allocator");
286 if ((allocator_type != "iterative") && (allocator_type != "random") &&
287 (allocator_type != "flq")) {
288 // Unsupported allocator type used.
289 isc_throw(DhcpConfigError, "supported allocators are: iterative, random and flq");
290 }
291 network->setAllocatorType(allocator_type);
292 }
293}
294
295void
297 Network6Ptr& network) {
298 if (network_data->contains("pd-allocator")) {
299 auto allocator_type = getString(network_data, "pd-allocator");
300 if ((allocator_type != "iterative") && (allocator_type != "random") &&
301 (allocator_type != "flq")) {
302 // Unsupported allocator type used.
303 isc_throw(DhcpConfigError, "supported allocators are: iterative, random and flq");
304 }
305 network->setPdAllocatorType(allocator_type);
306 }
307}
308
309void
311 Network4Ptr& network) {
312 if (network_data->contains("offer-lifetime")) {
313 auto value = getInteger(network_data, "offer-lifetime");
314 if (value < 0) {
315 isc_throw(DhcpConfigError, "the value of offer-lifetime '"
316 << value << "' must be a positive number ("
317 << getPosition("offer-lifetime", network_data) << ")");
318 }
319
320 network->setOfferLft(value);
321 }
322}
323
324
325} // end of namespace isc::dhcp
326} // 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 create(const Position &pos=ZERO_POSITION())
Definition: data.cc:249
target_type getAndConvert(isc::data::ConstElementPtr scope, const std::string &name, const std::string &type_name)
Returns a converted value from a scope.
static const data::Element::Position & getPosition(const std::string &name, const data::ConstElementPtr parent)
Utility method that returns position of an element.
static double getDouble(const ConstElementPtr &scope, const std::string &name)
Returns a floating point parameter from a scope.
static std::string getString(isc::data::ConstElementPtr scope, const std::string &name)
Returns a string parameter from a scope.
const isc::util::Triplet< uint32_t > parseIntTriplet(const data::ConstElementPtr &scope, const std::string &name)
Parses an integer triplet.
static bool getBoolean(isc::data::ConstElementPtr scope, const std::string &name)
Returns a boolean parameter from a scope.
static int64_t getInteger(isc::data::ConstElementPtr scope, const std::string &name)
Returns an integer parameter from a scope.
void parseCacheParams(const data::ConstElementPtr &network_data, NetworkPtr &network)
Parses parameters related to lease cache settings.
void parseAllocatorParams(const data::ConstElementPtr &network_data, NetworkPtr &network)
Parses parameters pertaining to allocator selection.
void parseDdnsParams(const data::ConstElementPtr &network_data, NetworkPtr &network)
Parses parameters pertaining to DDNS behavior.
void parseCommon(const data::ConstElementPtr &network_data, NetworkPtr &network)
Parses common parameters.
static void moveReservationMode(isc::data::ElementPtr config)
Moves deprecated reservation-mode parameter to new reservations flags.
void parseTeePercents(const data::ConstElementPtr &network_data, NetworkPtr &network)
Parses parameters related to "percent" timers settings.
void parsePdAllocatorParams(const data::ConstElementPtr &network_data, Network6Ptr &network)
Parses parameters pertaining to prefix delegation allocator selection.
void parseOfferLft(const data::ConstElementPtr &network_data, Network4Ptr &network)
Parses offer-lifetime parameter (v4 only)
static ReplaceClientNameMode stringToReplaceClientNameMode(const std::string &mode_str)
Converts labels to ReplaceClientNameMode enum values.
ReplaceClientNameMode
Defines the client name replacement modes.
Definition: d2_client_cfg.h:76
To be removed. Please use ConfigError instead.
A template representing an optional value.
Definition: optional.h:36
T get() const
Retrieves the encapsulated value.
Definition: optional.h:114
void unspecified(bool unspecified)
Modifies the flag that indicates whether the value is specified or unspecified.
Definition: optional.h:136
Implements a regular expression based string scrubber.
Definition: str.h:221
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition: macros.h:26
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:29
boost::shared_ptr< Element > ElementPtr
Definition: data.h:28
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition: dhcpsrv_log.h:56
boost::shared_ptr< Network4 > Network4Ptr
Pointer to the Network4 object.
Definition: network.h:1413
const isc::log::MessageID DHCPSRV_CFGMGR_RENEW_GTR_REBIND
boost::shared_ptr< CfgGlobals > CfgGlobalsPtr
Non-const shared pointer to a CfgGlobals instance.
Definition: cfg_globals.h:168
boost::shared_ptr< Network6 > Network6Ptr
Pointer to the Network6 object.
Definition: network.h:1418
boost::shared_ptr< Network > NetworkPtr
Pointer to the Network object.
Definition: network.h:73
std::unique_ptr< StringSanitizer > StringSanitizerPtr
Type representing the pointer to the StringSanitizer.
Definition: str.h:262
Defines the logger used by the top-level component of kea-lfc.