File: | home/fedora/workspace/kea-dev/clang-static-analyzer/src/lib/dhcpsrv/parsers/host_reservation_parser.cc |
Warning: | line 127, column 18 Value stored to 'prefix_len' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | // Copyright (C) 2014-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 <asiolink/io_address.h> |
9 | #include <asiolink/addr_utilities.h> |
10 | #include <dhcpsrv/cfgmgr.h> |
11 | #include <dhcpsrv/parsers/host_reservation_parser.h> |
12 | #include <dhcpsrv/parsers/option_data_parser.h> |
13 | #include <boost/lexical_cast.hpp> |
14 | #include <algorithm> |
15 | #include <sys/socket.h> |
16 | #include <sstream> |
17 | #include <string> |
18 | |
19 | using namespace isc::asiolink; |
20 | using namespace isc::data; |
21 | |
22 | namespace isc { |
23 | namespace dhcp { |
24 | |
25 | namespace { |
26 | |
27 | /// @brief Returns set of the supported parameters for DHCPv4. |
28 | /// |
29 | /// This function returns the set of supported parameters for |
30 | /// host reservation in DHCPv4. |
31 | /// |
32 | /// @param identifiers_only Indicates if the function should only |
33 | /// return supported host identifiers (if true) or all supported |
34 | /// parameters (if false). |
35 | const std::set<std::string>& |
36 | getSupportedParams4(const bool identifiers_only = false) { |
37 | // Holds set of host identifiers. |
38 | static std::set<std::string> identifiers_set; |
39 | // Holds set of all supported parameters, including identifiers. |
40 | static std::set<std::string> params_set; |
41 | // If this is first execution of this function, we need |
42 | // to initialize the set. |
43 | if (identifiers_set.empty()) { |
44 | identifiers_set.insert("hw-address"); |
45 | identifiers_set.insert("duid"); |
46 | identifiers_set.insert("circuit-id"); |
47 | identifiers_set.insert("client-id"); |
48 | identifiers_set.insert("flex-id"); |
49 | } |
50 | // Copy identifiers and add all other parameters. |
51 | if (params_set.empty()) { |
52 | params_set = identifiers_set; |
53 | params_set.insert("hostname"); |
54 | params_set.insert("ip-address"); |
55 | params_set.insert("option-data"); |
56 | params_set.insert("next-server"); |
57 | params_set.insert("server-hostname"); |
58 | params_set.insert("boot-file-name"); |
59 | params_set.insert("client-classes"); |
60 | params_set.insert("user-context"); |
61 | } |
62 | return (identifiers_only ? identifiers_set : params_set); |
63 | } |
64 | |
65 | /// @brief Returns set of the supported parameters for DHCPv6. |
66 | /// |
67 | /// This function returns the set of supported parameters for |
68 | /// host reservation in DHCPv6. |
69 | /// |
70 | /// @param identifiers_only Indicates if the function should only |
71 | /// return supported host identifiers (if true) or all supported |
72 | /// parameters (if false). |
73 | const std::set<std::string>& |
74 | getSupportedParams6(const bool identifiers_only = false) { |
75 | // Holds set of host identifiers. |
76 | static std::set<std::string> identifiers_set; |
77 | // Holds set of all supported parameters, including identifiers. |
78 | static std::set<std::string> params_set; |
79 | // If this is first execution of this function, we need |
80 | // to initialize the set. |
81 | if (identifiers_set.empty()) { |
82 | identifiers_set.insert("hw-address"); |
83 | identifiers_set.insert("duid"); |
84 | identifiers_set.insert("flex-id"); |
85 | } |
86 | // Copy identifiers and add all other parameters. |
87 | if (params_set.empty()) { |
88 | params_set = identifiers_set; |
89 | params_set.insert("hostname"); |
90 | params_set.insert("ip-addresses"); |
91 | params_set.insert("prefixes"); |
92 | params_set.insert("excluded-prefixes"); |
93 | params_set.insert("option-data"); |
94 | params_set.insert("client-classes"); |
95 | params_set.insert("user-context"); |
96 | } |
97 | return (identifiers_only ? identifiers_set : params_set); |
98 | } |
99 | |
100 | /// @brief Extract the prefix from the value specified in |
101 | /// the following format: 2001:db8:2000::/64. |
102 | /// |
103 | /// @param prefix Prefix in text format. |
104 | /// @param[out] addr Address part of the prefix. |
105 | /// @param[out] len Length part of the prefix. |
106 | /// @param msg Message to prepend to first error log. |
107 | void |
108 | parsePrefix(std::string prefix, IOAddress& addr, uint8_t& len, std::string msg) { |
109 | // The slash is mandatory for prefixes. If there is no slash, |
110 | // return an error. |
111 | size_t len_pos = prefix.find('/'); |
112 | if (len_pos == std::string::npos) { |
113 | isc_throw(DhcpConfigError, msg << " requires prefix length "do { std::ostringstream oss__; oss__ << msg << " requires prefix length " << "be specified in '" << prefix << "'"; throw DhcpConfigError("parsers/host_reservation_parser.cc", 114, oss__ .str().c_str()); } while (1) |
114 | << "be specified in '" << prefix << "'")do { std::ostringstream oss__; oss__ << msg << " requires prefix length " << "be specified in '" << prefix << "'"; throw DhcpConfigError("parsers/host_reservation_parser.cc", 114, oss__ .str().c_str()); } while (1); |
115 | } else if (len_pos >= prefix.length() - 1) { |
116 | // If there is nothing after the slash, we should also |
117 | // report an error. |
118 | isc_throw(DhcpConfigError, "prefix '" << prefixdo { std::ostringstream oss__; oss__ << "prefix '" << prefix << "' requires length after '/'"; throw DhcpConfigError ("parsers/host_reservation_parser.cc", 119, oss__.str().c_str ()); } while (1) |
119 | << "' requires length after '/'")do { std::ostringstream oss__; oss__ << "prefix '" << prefix << "' requires length after '/'"; throw DhcpConfigError ("parsers/host_reservation_parser.cc", 119, oss__.str().c_str ()); } while (1); |
120 | |
121 | } |
122 | |
123 | // Convert the prefix length from the string to the number. |
124 | // Note, that we don't use the uint8_t type as the lexical cast |
125 | // would expect a character, e.g. 'a', instead of prefix length, |
126 | // e.g. '64'. |
127 | unsigned int prefix_len = len; |
Value stored to 'prefix_len' during its initialization is never read | |
128 | try { |
129 | prefix_len = boost::lexical_cast<unsigned int>(prefix.substr(len_pos + 1)); |
130 | } catch (const boost::bad_lexical_cast&) { |
131 | isc_throw(DhcpConfigError, "prefix length value '"do { std::ostringstream oss__; oss__ << "prefix length value '" << prefix.substr(len_pos + 1) << "' is invalid"; throw DhcpConfigError("parsers/host_reservation_parser.cc", 132 , oss__.str().c_str()); } while (1) |
132 | << prefix.substr(len_pos + 1) << "' is invalid")do { std::ostringstream oss__; oss__ << "prefix length value '" << prefix.substr(len_pos + 1) << "' is invalid"; throw DhcpConfigError("parsers/host_reservation_parser.cc", 132 , oss__.str().c_str()); } while (1); |
133 | } |
134 | if ((prefix_len == 0) || (prefix_len > 128)) { |
135 | isc_throw(OutOfRange,do { std::ostringstream oss__; oss__ << "'prefix-len' value must be in range of [1..128]" ; throw OutOfRange("parsers/host_reservation_parser.cc", 136, oss__.str().c_str()); } while (1) |
136 | "'prefix-len' value must be in range of [1..128]")do { std::ostringstream oss__; oss__ << "'prefix-len' value must be in range of [1..128]" ; throw OutOfRange("parsers/host_reservation_parser.cc", 136, oss__.str().c_str()); } while (1); |
137 | } |
138 | len = static_cast<uint8_t>(prefix_len); |
139 | |
140 | // Remove the slash character and the prefix length from the |
141 | // parsed value. |
142 | prefix.erase(len_pos); |
143 | addr = IOAddress(prefix); |
144 | |
145 | if (len != 128) { |
146 | IOAddress first_address = firstAddrInPrefix(addr, len); |
147 | if (first_address != addr) { |
148 | isc_throw(BadValue, "Prefix address: " << addrdo { std::ostringstream oss__; oss__ << "Prefix address: " << addr << " exceeds prefix/prefix-len pair: " << first_address << "/" << prefix_len; throw BadValue ("parsers/host_reservation_parser.cc", 150, oss__.str().c_str ()); } while (1) |
149 | << " exceeds prefix/prefix-len pair: " << first_addressdo { std::ostringstream oss__; oss__ << "Prefix address: " << addr << " exceeds prefix/prefix-len pair: " << first_address << "/" << prefix_len; throw BadValue ("parsers/host_reservation_parser.cc", 150, oss__.str().c_str ()); } while (1) |
150 | << "/" << prefix_len)do { std::ostringstream oss__; oss__ << "Prefix address: " << addr << " exceeds prefix/prefix-len pair: " << first_address << "/" << prefix_len; throw BadValue ("parsers/host_reservation_parser.cc", 150, oss__.str().c_str ()); } while (1); |
151 | } |
152 | } |
153 | } |
154 | |
155 | } |
156 | |
157 | HostPtr |
158 | HostReservationParser::parse(const SubnetID& subnet_id, |
159 | isc::data::ConstElementPtr reservation_data, |
160 | bool encapsulate_options) { |
161 | return (parseInternal(subnet_id, reservation_data, encapsulate_options)); |
162 | } |
163 | |
164 | HostPtr |
165 | HostReservationParser::parseInternal(const SubnetID&, |
166 | isc::data::ConstElementPtr reservation_data, |
167 | bool) { |
168 | std::string identifier; |
169 | std::string identifier_name; |
170 | std::string hostname; |
171 | ConstElementPtr user_context; |
172 | HostPtr host; |
173 | |
174 | try { |
175 | // Gather those parameters that are common for both IPv4 and IPv6 |
176 | // reservations. |
177 | for (auto const& element : reservation_data->mapValue()) { |
178 | // Check if we support this parameter. |
179 | if (!isSupportedParameter(element.first)) { |
180 | isc_throw(DhcpConfigError, "unsupported configuration"do { std::ostringstream oss__; oss__ << "unsupported configuration" " parameter '" << element.first << "'"; throw DhcpConfigError ("parsers/host_reservation_parser.cc", 181, oss__.str().c_str ()); } while (1) |
181 | " parameter '" << element.first << "'")do { std::ostringstream oss__; oss__ << "unsupported configuration" " parameter '" << element.first << "'"; throw DhcpConfigError ("parsers/host_reservation_parser.cc", 181, oss__.str().c_str ()); } while (1); |
182 | } |
183 | |
184 | if (isIdentifierParameter(element.first)) { |
185 | if (!identifier.empty()) { |
186 | isc_throw(DhcpConfigError, "the '" << element.firstdo { std::ostringstream oss__; oss__ << "the '" << element.first << "' and '" << identifier_name << "' are mutually exclusive"; throw DhcpConfigError("parsers/host_reservation_parser.cc" , 188, oss__.str().c_str()); } while (1) |
187 | << "' and '" << identifier_namedo { std::ostringstream oss__; oss__ << "the '" << element.first << "' and '" << identifier_name << "' are mutually exclusive"; throw DhcpConfigError("parsers/host_reservation_parser.cc" , 188, oss__.str().c_str()); } while (1) |
188 | << "' are mutually exclusive")do { std::ostringstream oss__; oss__ << "the '" << element.first << "' and '" << identifier_name << "' are mutually exclusive"; throw DhcpConfigError("parsers/host_reservation_parser.cc" , 188, oss__.str().c_str()); } while (1); |
189 | } |
190 | identifier = element.second->stringValue(); |
191 | identifier_name = element.first; |
192 | |
193 | } else if (element.first == "hostname") { |
194 | hostname = element.second->stringValue(); |
195 | } else if (element.first == "user-context") { |
196 | user_context = element.second; |
197 | } |
198 | } |
199 | |
200 | // Host identifier is a must. |
201 | if (identifier_name.empty()) { |
202 | // If there is no identifier specified, we have to display an |
203 | // error message and include the information what identifiers |
204 | // are supported. |
205 | std::ostringstream s; |
206 | for (auto const& param_name : getSupportedParameters(true)) { |
207 | if (s.tellp() != std::streampos(0)) { |
208 | s << ", "; |
209 | } |
210 | s << param_name; |
211 | } |
212 | isc_throw(DhcpConfigError, "one of the supported identifiers must"do { std::ostringstream oss__; oss__ << "one of the supported identifiers must" " be specified for host reservation: " << s.str(); throw DhcpConfigError("parsers/host_reservation_parser.cc", 214, oss__ .str().c_str()); } while (1) |
213 | " be specified for host reservation: "do { std::ostringstream oss__; oss__ << "one of the supported identifiers must" " be specified for host reservation: " << s.str(); throw DhcpConfigError("parsers/host_reservation_parser.cc", 214, oss__ .str().c_str()); } while (1) |
214 | << s.str())do { std::ostringstream oss__; oss__ << "one of the supported identifiers must" " be specified for host reservation: " << s.str(); throw DhcpConfigError("parsers/host_reservation_parser.cc", 214, oss__ .str().c_str()); } while (1); |
215 | |
216 | } |
217 | |
218 | // Create a host object from the basic parameters we already parsed. |
219 | host.reset(new Host(identifier, identifier_name, SUBNET_ID_UNUSED, |
220 | SUBNET_ID_UNUSED, IOAddress("0.0.0.0"), hostname)); |
221 | |
222 | // Add user context |
223 | if (user_context) { |
224 | host->setContext(user_context); |
225 | } |
226 | } catch (const std::exception& ex) { |
227 | // Append line number where the error occurred. |
228 | isc_throw(DhcpConfigError, ex.what() << " ("do { std::ostringstream oss__; oss__ << ex.what() << " (" << reservation_data->getPosition() << ")" ; throw DhcpConfigError("parsers/host_reservation_parser.cc", 229, oss__.str().c_str()); } while (1) |
229 | << reservation_data->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() << " (" << reservation_data->getPosition() << ")" ; throw DhcpConfigError("parsers/host_reservation_parser.cc", 229, oss__.str().c_str()); } while (1); |
230 | } |
231 | |
232 | return (host); |
233 | } |
234 | |
235 | bool |
236 | HostReservationParser::isIdentifierParameter(const std::string& param_name) const { |
237 | return (getSupportedParameters(true).count(param_name) > 0); |
238 | } |
239 | |
240 | bool |
241 | HostReservationParser::isSupportedParameter(const std::string& param_name) const { |
242 | return (getSupportedParameters(false).count(param_name) > 0); |
243 | } |
244 | |
245 | HostPtr |
246 | HostReservationParser4::parseInternal(const SubnetID& subnet_id, |
247 | isc::data::ConstElementPtr reservation_data, |
248 | bool encapsulate_options) { |
249 | HostPtr host = HostReservationParser::parseInternal(subnet_id, reservation_data, |
250 | encapsulate_options); |
251 | |
252 | host->setIPv4SubnetID(subnet_id); |
253 | |
254 | for (auto const& element : reservation_data->mapValue()) { |
255 | // For 'option-data' element we will use another parser which |
256 | // already returns errors with position appended, so don't |
257 | // surround it with try-catch. |
258 | if (element.first == "option-data") { |
259 | CfgOptionPtr cfg_option = host->getCfgOption4(); |
260 | |
261 | // This parser is converted to SimpleParser already. It |
262 | // parses the Element structure immediately, there's no need |
263 | // to go through build/commit phases. |
264 | OptionDataListParser parser(AF_INET2); |
265 | parser.parse(cfg_option, element.second, encapsulate_options); |
266 | |
267 | // Everything else should be surrounded with try-catch to append |
268 | // position. |
269 | } else { |
270 | try { |
271 | if (element.first == "ip-address") { |
272 | host->setIPv4Reservation(IOAddress(element.second-> |
273 | stringValue())); |
274 | } else if (element.first == "next-server") { |
275 | host->setNextServer(IOAddress(element.second->stringValue())); |
276 | |
277 | } else if (element.first == "server-hostname") { |
278 | host->setServerHostname(element.second->stringValue()); |
279 | |
280 | } else if (element.first == "boot-file-name") { |
281 | host->setBootFileName(element.second->stringValue()); |
282 | |
283 | } else if (element.first == "client-classes") { |
284 | for (auto const& class_element : element.second->listValue()) { |
285 | host->addClientClass4(class_element->stringValue()); |
286 | } |
287 | } |
288 | |
289 | } catch (const std::exception& ex) { |
290 | // Append line number where the error occurred. |
291 | isc_throw(DhcpConfigError, ex.what() << " ("do { std::ostringstream oss__; oss__ << ex.what() << " (" << element.second->getPosition() << ")"; throw DhcpConfigError("parsers/host_reservation_parser.cc", 292 , oss__.str().c_str()); } while (1) |
292 | << element.second->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() << " (" << element.second->getPosition() << ")"; throw DhcpConfigError("parsers/host_reservation_parser.cc", 292 , oss__.str().c_str()); } while (1); |
293 | } |
294 | } |
295 | } |
296 | |
297 | return (host); |
298 | } |
299 | |
300 | const std::set<std::string>& |
301 | HostReservationParser4::getSupportedParameters(const bool identifiers_only) const { |
302 | return (getSupportedParams4(identifiers_only)); |
303 | } |
304 | |
305 | HostPtr |
306 | HostReservationParser6::parseInternal(const SubnetID& subnet_id, |
307 | isc::data::ConstElementPtr reservation_data, |
308 | bool encapsulate_options) { |
309 | HostPtr host = HostReservationParser::parseInternal(subnet_id, reservation_data, |
310 | encapsulate_options); |
311 | |
312 | host->setIPv6SubnetID(subnet_id); |
313 | |
314 | ConstElementPtr option_data = reservation_data->get("option-data"); |
315 | ConstElementPtr ip_addresses = reservation_data->get("ip-addresses"); |
316 | ConstElementPtr prefixes = reservation_data->get("prefixes"); |
317 | ConstElementPtr excluded_prefixes = reservation_data->get("excluded-prefixes"); |
318 | ConstElementPtr client_classes = reservation_data->get("client-classes"); |
319 | |
320 | // Parse option values. Note that the configuration option parser |
321 | // returns errors with position information appended, so there is no |
322 | // need to surround it with try-clause (and rethrow with position |
323 | // appended). |
324 | if (option_data) { |
325 | CfgOptionPtr cfg_option = host->getCfgOption6(); |
326 | |
327 | // This parser is converted to SimpleParser already. It |
328 | // parses the Element structure immediately, there's no need |
329 | // to go through build/commit phases. |
330 | OptionDataListParser parser(AF_INET610); |
331 | parser.parse(cfg_option, option_data, encapsulate_options); |
332 | } |
333 | |
334 | if (ip_addresses) { |
335 | for (size_t idx = 0; idx < ip_addresses->size(); ++idx) { |
336 | ConstElementPtr element = ip_addresses->get(idx); |
337 | try { |
338 | // For the IPv6 address the prefix length is 128 and the |
339 | // value specified in the list is a reserved address. |
340 | std::string addr = element->stringValue(); |
341 | // Create a reservation for the address. |
342 | host->addReservation(IPv6Resrv(IPv6Resrv::TYPE_NA, |
343 | IOAddress(addr), 128)); |
344 | } catch (const std::exception& ex) { |
345 | // Append line number where the error occurred. |
346 | isc_throw(DhcpConfigError, ex.what() << " ("do { std::ostringstream oss__; oss__ << ex.what() << " (" << element->getPosition() << ")"; throw DhcpConfigError ("parsers/host_reservation_parser.cc", 347, oss__.str().c_str ()); } while (1) |
347 | << element->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() << " (" << element->getPosition() << ")"; throw DhcpConfigError ("parsers/host_reservation_parser.cc", 347, oss__.str().c_str ()); } while (1); |
348 | } |
349 | } |
350 | } |
351 | |
352 | if (excluded_prefixes) { |
353 | if (!prefixes) { |
354 | isc_throw(DhcpConfigError, "'excluded-prefixes' parameter "do { std::ostringstream oss__; oss__ << "'excluded-prefixes' parameter " "requires the 'prefixes' parameter"; throw DhcpConfigError("parsers/host_reservation_parser.cc" , 355, oss__.str().c_str()); } while (1) |
355 | "requires the 'prefixes' parameter")do { std::ostringstream oss__; oss__ << "'excluded-prefixes' parameter " "requires the 'prefixes' parameter"; throw DhcpConfigError("parsers/host_reservation_parser.cc" , 355, oss__.str().c_str()); } while (1); |
356 | } |
357 | if (excluded_prefixes->size() != prefixes->size()) { |
358 | isc_throw(DhcpConfigError, "'excluded-prefixes' parameter "do { std::ostringstream oss__; oss__ << "'excluded-prefixes' parameter " "does not match the 'prefixes' parameter: " << excluded_prefixes ->size() << " != " << prefixes->size(); throw DhcpConfigError("parsers/host_reservation_parser.cc", 361, oss__ .str().c_str()); } while (1) |
359 | "does not match the 'prefixes' parameter: "do { std::ostringstream oss__; oss__ << "'excluded-prefixes' parameter " "does not match the 'prefixes' parameter: " << excluded_prefixes ->size() << " != " << prefixes->size(); throw DhcpConfigError("parsers/host_reservation_parser.cc", 361, oss__ .str().c_str()); } while (1) |
360 | << excluded_prefixes->size() << " != "do { std::ostringstream oss__; oss__ << "'excluded-prefixes' parameter " "does not match the 'prefixes' parameter: " << excluded_prefixes ->size() << " != " << prefixes->size(); throw DhcpConfigError("parsers/host_reservation_parser.cc", 361, oss__ .str().c_str()); } while (1) |
361 | << prefixes->size())do { std::ostringstream oss__; oss__ << "'excluded-prefixes' parameter " "does not match the 'prefixes' parameter: " << excluded_prefixes ->size() << " != " << prefixes->size(); throw DhcpConfigError("parsers/host_reservation_parser.cc", 361, oss__ .str().c_str()); } while (1); |
362 | } |
363 | } |
364 | |
365 | if (prefixes) { |
366 | for (size_t idx = 0; idx < prefixes->size(); ++idx) { |
367 | ConstElementPtr element = prefixes->get(idx); |
368 | try { |
369 | std::string prefix = element->stringValue(); |
370 | IOAddress addr("::"); |
371 | uint8_t prefix_len(128); |
372 | parsePrefix(prefix, addr, prefix_len, "prefix reservation"); |
373 | IPv6Resrv res(IPv6Resrv::TYPE_PD, addr, prefix_len); |
374 | std::string exclude(""); |
375 | if (excluded_prefixes) { |
376 | element = excluded_prefixes->get(idx); |
377 | exclude = element->stringValue(); |
378 | } |
379 | if (!exclude.empty()) { |
380 | IOAddress excluded_prefix("::"); |
381 | uint8_t excluded_prefix_len(0); |
382 | parsePrefix(exclude, excluded_prefix, excluded_prefix_len, |
383 | "exclude prefix"); |
384 | // setPDExclude calls the Option6PDExclude constructor |
385 | // which throws on invalid prefix. |
386 | res.setPDExclude(excluded_prefix, excluded_prefix_len); |
387 | } |
388 | host->addReservation(res); |
389 | } catch (const std::exception& ex) { |
390 | // Append line number where the error occurred. |
391 | isc_throw(DhcpConfigError, ex.what() << " ("do { std::ostringstream oss__; oss__ << ex.what() << " (" << element->getPosition() << ")"; throw DhcpConfigError ("parsers/host_reservation_parser.cc", 392, oss__.str().c_str ()); } while (1) |
392 | << element->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() << " (" << element->getPosition() << ")"; throw DhcpConfigError ("parsers/host_reservation_parser.cc", 392, oss__.str().c_str ()); } while (1); |
393 | } |
394 | } |
395 | } |
396 | |
397 | if (client_classes) { |
398 | try { |
399 | for (auto const& class_element : client_classes->listValue()) { |
400 | host->addClientClass6(class_element->stringValue()); |
401 | } |
402 | } catch (const std::exception& ex) { |
403 | // Append line number where the error occurred. |
404 | isc_throw(DhcpConfigError, ex.what() << " ("do { std::ostringstream oss__; oss__ << ex.what() << " (" << client_classes->getPosition() << ")"; throw DhcpConfigError("parsers/host_reservation_parser.cc", 405 , oss__.str().c_str()); } while (1) |
405 | << client_classes->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() << " (" << client_classes->getPosition() << ")"; throw DhcpConfigError("parsers/host_reservation_parser.cc", 405 , oss__.str().c_str()); } while (1); |
406 | } |
407 | } |
408 | |
409 | return (host); |
410 | } |
411 | |
412 | const std::set<std::string>& |
413 | HostReservationParser6::getSupportedParameters(const bool identifiers_only) const { |
414 | return (getSupportedParams6(identifiers_only)); |
415 | } |
416 | |
417 | HostReservationIdsParser::HostReservationIdsParser() |
418 | : staging_cfg_() { |
419 | } |
420 | |
421 | void |
422 | HostReservationIdsParser::parse(isc::data::ConstElementPtr ids_list) { |
423 | parseInternal(ids_list); |
424 | } |
425 | |
426 | void |
427 | HostReservationIdsParser::parseInternal(isc::data::ConstElementPtr ids_list) { |
428 | // Remove existing identifier types. |
429 | staging_cfg_->clearIdentifierTypes(); |
430 | |
431 | for (auto const& element : ids_list->listValue()) { |
432 | std::string id_name = element->stringValue(); |
433 | try { |
434 | if (id_name != "auto") { |
435 | if (!isSupportedIdentifier(id_name)) { |
436 | isc_throw(isc::BadValue, "unsupported identifier '"do { std::ostringstream oss__; oss__ << "unsupported identifier '" << id_name << "'"; throw isc::BadValue("parsers/host_reservation_parser.cc" , 437, oss__.str().c_str()); } while (1) |
437 | << id_name << "'")do { std::ostringstream oss__; oss__ << "unsupported identifier '" << id_name << "'"; throw isc::BadValue("parsers/host_reservation_parser.cc" , 437, oss__.str().c_str()); } while (1); |
438 | } |
439 | staging_cfg_->addIdentifierType(id_name); |
440 | |
441 | } else { |
442 | // 'auto' is mutually exclusive with other values. If there |
443 | // are any values in the configuration already it means that |
444 | // some other values have already been specified. |
445 | if (!staging_cfg_->getIdentifierTypes().empty()) { |
446 | isc_throw(isc::BadValue, "if 'auto' keyword is used,"do { std::ostringstream oss__; oss__ << "if 'auto' keyword is used," " no other values can be specified within '" "host-reservation-identifiers' list" ; throw isc::BadValue("parsers/host_reservation_parser.cc", 448 , oss__.str().c_str()); } while (1) |
447 | " no other values can be specified within '"do { std::ostringstream oss__; oss__ << "if 'auto' keyword is used," " no other values can be specified within '" "host-reservation-identifiers' list" ; throw isc::BadValue("parsers/host_reservation_parser.cc", 448 , oss__.str().c_str()); } while (1) |
448 | "host-reservation-identifiers' list")do { std::ostringstream oss__; oss__ << "if 'auto' keyword is used," " no other values can be specified within '" "host-reservation-identifiers' list" ; throw isc::BadValue("parsers/host_reservation_parser.cc", 448 , oss__.str().c_str()); } while (1); |
449 | } |
450 | // Iterate over all identifier types and for those supported |
451 | // in a given context (DHCPv4 or DHCPv6) add the identifier type |
452 | // to the configuration. |
453 | for (unsigned int i = 0; |
454 | i <= static_cast<unsigned int>(Host::LAST_IDENTIFIER_TYPE); |
455 | ++i) { |
456 | std::string supported_id_name = |
457 | Host::getIdentifierName(static_cast<Host::IdentifierType>(i)); |
458 | if (isSupportedIdentifier(supported_id_name)) { |
459 | staging_cfg_->addIdentifierType(supported_id_name); |
460 | } |
461 | } |
462 | } |
463 | |
464 | } catch (const std::exception& ex) { |
465 | // Append line number where the error occurred. |
466 | isc_throw(DhcpConfigError, ex.what() << " ("do { std::ostringstream oss__; oss__ << ex.what() << " (" << element->getPosition() << ")"; throw DhcpConfigError ("parsers/host_reservation_parser.cc", 467, oss__.str().c_str ()); } while (1) |
467 | << element->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() << " (" << element->getPosition() << ")"; throw DhcpConfigError ("parsers/host_reservation_parser.cc", 467, oss__.str().c_str ()); } while (1); |
468 | } |
469 | } |
470 | |
471 | // The parsed list must not be empty. |
472 | if (staging_cfg_->getIdentifierTypes().empty()) { |
473 | isc_throw(DhcpConfigError, "'host-reservation-identifiers' list must not"do { std::ostringstream oss__; oss__ << "'host-reservation-identifiers' list must not" " be empty (" << ids_list->getPosition() << ")" ; throw DhcpConfigError("parsers/host_reservation_parser.cc", 474, oss__.str().c_str()); } while (1) |
474 | " be empty (" << ids_list->getPosition() << ")")do { std::ostringstream oss__; oss__ << "'host-reservation-identifiers' list must not" " be empty (" << ids_list->getPosition() << ")" ; throw DhcpConfigError("parsers/host_reservation_parser.cc", 474, oss__.str().c_str()); } while (1); |
475 | } |
476 | |
477 | } |
478 | |
479 | HostReservationIdsParser4::HostReservationIdsParser4() |
480 | : HostReservationIdsParser() { |
481 | staging_cfg_ = CfgMgr::instance().getStagingCfg()->getCfgHostOperations4(); |
482 | } |
483 | |
484 | bool |
485 | HostReservationIdsParser4::isSupportedIdentifier(const std::string& id_name) const { |
486 | return (getSupportedParams4(true).count(id_name) > 0); |
487 | } |
488 | |
489 | HostReservationIdsParser6::HostReservationIdsParser6() |
490 | : HostReservationIdsParser() { |
491 | staging_cfg_ = CfgMgr::instance().getStagingCfg()->getCfgHostOperations6(); |
492 | } |
493 | |
494 | bool |
495 | HostReservationIdsParser6::isSupportedIdentifier(const std::string& id_name) const { |
496 | return (getSupportedParams6(true).count(id_name) > 0); |
497 | } |
498 | |
499 | } // end of namespace isc::dhcp |
500 | } // end of namespace isc |