Kea  2.1.7-git
base_network_parser.cc
Go to the documentation of this file.
1 // Copyright (C) 2019-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 #include <util/triplet.h>
10 #include <util/optional.h>
11 #include <util/strutil.h>
12 
13 using namespace isc::data;
14 using namespace isc::util;
15 
16 namespace isc {
17 namespace dhcp {
18 
19 void
20 BaseNetworkParser::moveReservationMode(ElementPtr config) {
21  if (!config->contains("reservation-mode")) {
22  return;
23  }
24  if (config->contains("reservations-global") ||
25  config->contains("reservations-in-subnet") ||
26  config->contains("reservations-out-of-pool")) {
27  isc_throw(DhcpConfigError, "invalid use of both 'reservation-mode'"
28  " and one of 'reservations-global', 'reservations-in-subnet'"
29  " or 'reservations-out-of-pool' parameters");
30  }
31  std::string hr_mode = getString(config, "reservation-mode");
32  if ((hr_mode == "disabled") || (hr_mode == "off")) {
33  config->set("reservations-global", Element::create(false));
34  config->set("reservations-in-subnet", Element::create(false));
35  } else if (hr_mode == "out-of-pool") {
36  config->set("reservations-global", Element::create(false));
37  config->set("reservations-in-subnet", Element::create(true));
38  config->set("reservations-out-of-pool", Element::create(true));
39  } else if (hr_mode == "global") {
40  config->set("reservations-global", Element::create(true));
41  config->set("reservations-in-subnet", Element::create(false));
42  } else if (hr_mode == "all") {
43  config->set("reservations-global", Element::create(false));
44  config->set("reservations-in-subnet", Element::create(true));
45  config->set("reservations-out-of-pool", Element::create(false));
46  } else {
47  isc_throw(DhcpConfigError, "invalid reservation-mode parameter: '"
48  << hr_mode << "' ("
49  << getPosition("reservation-mode", config) << ")");
50  }
51  config->remove("reservation-mode");
52 }
53 
54 void
55 BaseNetworkParser::moveReservationMode(CfgGlobalsPtr config) {
56  if (!config->get(CfgGlobals::RESERVATION_MODE)) {
57  return;
58  }
59  if (config->get(CfgGlobals::RESERVATIONS_GLOBAL) ||
60  config->get(CfgGlobals::RESERVATIONS_IN_SUBNET) ||
61  config->get(CfgGlobals::RESERVATIONS_OUT_OF_POOL)) {
62  isc_throw(DhcpConfigError, "invalid use of both 'reservation-mode'"
63  " and one of 'reservations-global', 'reservations-in-subnet'"
64  " or 'reservations-out-of-pool' parameters");
65  }
66  std::string hr_mode = config->get(CfgGlobals::RESERVATION_MODE)->stringValue();
67  if ((hr_mode == "disabled") || (hr_mode == "off")) {
68  config->set(CfgGlobals::RESERVATIONS_GLOBAL, Element::create(false));
69  config->set(CfgGlobals::RESERVATIONS_IN_SUBNET, Element::create(false));
70  } else if (hr_mode == "out-of-pool") {
71  config->set(CfgGlobals::RESERVATIONS_GLOBAL, Element::create(false));
72  config->set(CfgGlobals::RESERVATIONS_IN_SUBNET, Element::create(true));
73  config->set(CfgGlobals::RESERVATIONS_OUT_OF_POOL, Element::create(true));
74  } else if (hr_mode == "global") {
75  config->set(CfgGlobals::RESERVATIONS_GLOBAL, Element::create(true));
76  config->set(CfgGlobals::RESERVATIONS_IN_SUBNET, Element::create(false));
77  } else if (hr_mode == "all") {
78  config->set(CfgGlobals::RESERVATIONS_GLOBAL, Element::create(false));
79  config->set(CfgGlobals::RESERVATIONS_IN_SUBNET, Element::create(true));
80  config->set("reservations-out-of-pool", Element::create(false));
81  } else {
82  isc_throw(DhcpConfigError, "invalid reservation-mode parameter: '"
83  << hr_mode << "' ("
84  << config->get(CfgGlobals::RESERVATION_MODE)->getPosition()
85  << ")");
86  }
87  config->set(CfgGlobals::RESERVATION_MODE, ConstElementPtr());
88 }
89 
90 void
91 BaseNetworkParser::parseCommon(const ConstElementPtr& network_data,
92  NetworkPtr& network) {
93  bool has_renew = network_data->contains("renew-timer");
94  bool has_rebind = network_data->contains("rebind-timer");
95  int64_t renew = -1;
96  int64_t rebind = -1;
97 
98  if (has_renew) {
99  renew = getInteger(network_data, "renew-timer");
100  if (renew < 0) {
101  isc_throw(DhcpConfigError, "the value of renew-timer ("
102  << renew << ") must be a positive number");
103  }
104  network->setT1(renew);
105  }
106 
107  if (has_rebind) {
108  rebind = getInteger(network_data, "rebind-timer");
109  if (rebind < 0) {
110  isc_throw(DhcpConfigError, "the value of rebind-timer ("
111  << rebind << ") must be a positive number");
112  }
113  network->setT2(rebind);
114  }
115 
116  if (has_renew && has_rebind && (renew > rebind)) {
117  isc_throw(DhcpConfigError, "the value of renew-timer (" << renew
118  << ") is greater than the value of rebind-timer ("
119  << rebind << ")");
120  }
121 
122  network->setValid(parseIntTriplet(network_data, "valid-lifetime"));
123 
124  if (network_data->contains("store-extended-info")) {
125  network->setStoreExtendedInfo(getBoolean(network_data,
126  "store-extended-info"));
127  }
128 
129  if (network_data->contains("reservations-global")) {
130  network->setReservationsGlobal(getBoolean(network_data,
131  "reservations-global"));
132  }
133 
134  if (network_data->contains("reservations-in-subnet")) {
135  network->setReservationsInSubnet(getBoolean(network_data,
136  "reservations-in-subnet"));
137  }
138 
139  if (network_data->contains("reservations-out-of-pool")) {
140  network->setReservationsOutOfPool(getBoolean(network_data,
141  "reservations-out-of-pool"));
142  }
143 }
144 
145 void
146 BaseNetworkParser::parseTeePercents(const ConstElementPtr& network_data,
147  NetworkPtr& network) {
148  bool calculate_tee_times = network->getCalculateTeeTimes();
149  if (network_data->contains("calculate-tee-times")) {
150  calculate_tee_times = getBoolean(network_data, "calculate-tee-times");
151  network->setCalculateTeeTimes(calculate_tee_times);
152  }
153 
154  Optional<double> t2_percent;
155  if (network_data->contains("t2-percent")) {
156  t2_percent = getDouble(network_data, "t2-percent");
157  }
158 
159  Optional<double> t1_percent;
160  if (network_data->contains("t1-percent")) {
161  t1_percent = getDouble(network_data, "t1-percent");
162  }
163  if (calculate_tee_times) {
164  if (!t2_percent.unspecified() && ((t2_percent.get() <= 0.0) ||
165  (t2_percent.get() >= 1.0))) {
166  isc_throw(DhcpConfigError, "t2-percent: " << t2_percent.get()
167  << " is invalid, it must be greater than 0.0 and less than 1.0");
168  }
169 
170  if (!t1_percent.unspecified() && ((t1_percent.get() <= 0.0) ||
171  (t1_percent.get() >= 1.0))) {
172  isc_throw(DhcpConfigError, "t1-percent: " << t1_percent.get()
173  << " is invalid it must be greater than 0.0 and less than 1.0");
174  }
175 
176  if (!t1_percent.unspecified() && !t2_percent.unspecified() &&
177  (t1_percent.get() >= t2_percent.get())) {
178  isc_throw(DhcpConfigError, "t1-percent: " << t1_percent.get()
179  << " is invalid, it must be less than t2-percent: "
180  << t2_percent.get());
181  }
182  }
183 
184  network->setT2Percent(t2_percent);
185  network->setT1Percent(t1_percent);
186 }
187 
188 void
189 BaseNetworkParser::parseCacheParams(const ConstElementPtr& network_data,
190  NetworkPtr& network) {
191  if (network_data->contains("cache-threshold")) {
192  double cache_threshold = getDouble(network_data, "cache-threshold");
193  if ((cache_threshold <= 0.0) || (cache_threshold >= 1.0)) {
194  isc_throw(DhcpConfigError, "cache-threshold: " << cache_threshold
195  << " is invalid, it must be greater than 0.0 and less than 1.0");
196  }
197  network->setCacheThreshold(cache_threshold);
198  }
199 
200  if (network_data->contains("cache-max-age")) {
201  network->setCacheMaxAge(getInteger(network_data, "cache-max-age"));
202  }
203 }
204 
205 void
206 BaseNetworkParser::parseDdnsParams(const data::ConstElementPtr& network_data,
207  NetworkPtr& network) {
208 
209  if (network_data->contains("ddns-send-updates")) {
210  network->setDdnsSendUpdates(getBoolean(network_data, "ddns-send-updates"));
211  }
212 
213  if (network_data->contains("ddns-override-no-update")) {
214  network->setDdnsOverrideNoUpdate(getBoolean(network_data, "ddns-override-no-update"));
215  }
216 
217  if (network_data->contains("ddns-override-client-update")) {
218  network->setDdnsOverrideClientUpdate(getBoolean(network_data, "ddns-override-client-update"));
219  }
220 
221  if (network_data->contains("ddns-replace-client-name")) {
222  network->setDdnsReplaceClientNameMode(getAndConvert<D2ClientConfig::ReplaceClientNameMode,
223  D2ClientConfig::stringToReplaceClientNameMode>
224  (network_data, "ddns-replace-client-name",
225  "ReplaceClientName mode"));
226  }
227 
228  if (network_data->contains("ddns-generated-prefix")) {
229  network->setDdnsGeneratedPrefix(getString(network_data, "ddns-generated-prefix"));
230  }
231 
232  if (network_data->contains("ddns-qualifying-suffix")) {
233  network->setDdnsQualifyingSuffix(getString(network_data, "ddns-qualifying-suffix"));
234  }
235 
236  std::string hostname_char_set;
237  if (network_data->contains("hostname-char-set")) {
238  hostname_char_set = getString(network_data, "hostname-char-set");
239  network->setHostnameCharSet(hostname_char_set);
240  }
241 
242  std::string hostname_char_replacement;
243  if (network_data->contains("hostname-char-replacement")) {
244  hostname_char_replacement = getString(network_data, "hostname-char-replacement");
245  network->setHostnameCharReplacement(hostname_char_replacement);
246  }
247 
248  // We need to validate sanitizer values here so we can detect problems and
249  // cause a configuration. We don't retain the compilation because it's not
250  // something we can inherit.
251  if (!hostname_char_set.empty()) {
252  try {
253  str::StringSanitizerPtr sanitizer(new str::StringSanitizer(hostname_char_set,
254  hostname_char_replacement));
255  } catch (const std::exception& ex) {
256  isc_throw(BadValue, "hostname-char-set '" << hostname_char_set
257  << "' is not a valid regular expression");
258  }
259  }
260 
261  if (network_data->contains("ddns-update-on-renew")) {
262  network->setDdnsUpdateOnRenew(getBoolean(network_data, "ddns-update-on-renew"));
263  }
264 
265  if (network_data->contains("ddns-use-conflict-resolution")) {
266  network->setDdnsUseConflictResolution(getBoolean(network_data, "ddns-use-conflict-resolution"));
267  }
268 }
269 
270 } // end of namespace isc::dhcp
271 } // end of namespace isc
void unspecified(bool unspecified)
Modifies the flag that indicates whether the value is specified or unspecified.
Definition: optional.h:136
boost::shared_ptr< Network > NetworkPtr
Pointer to the Network object.
Definition: network.h:41
boost::shared_ptr< CfgGlobals > CfgGlobalsPtr
Non-const shared pointer to a CfgGlobals instance.
Definition: cfg_globals.h:156
T get() const
Retrieves the encapsulated value.
Definition: optional.h:114
boost::shared_ptr< Element > ElementPtr
Definition: data.h:24
#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
To be removed. Please use ConfigError instead.
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:27
Implements a regular expression based string scrubber.
Definition: strutil.h:310
Defines the logger used by the top-level component of kea-lfc.
ReplaceClientNameMode
Defines the client name replacement modes.
Definition: d2_client_cfg.h:76
static ElementPtr create(const Position &pos=ZERO_POSITION())
Definition: data.cc:241
boost::shared_ptr< StringSanitizer > StringSanitizerPtr
Type representing the pointer to the StringSanitizer.
Definition: strutil.h:358