Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name host_reservation_parser.cc -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/fedora/workspace/kea-dev/clang-static-analyzer/src/lib/dhcpsrv -fcoverage-compilation-dir=/home/fedora/workspace/kea-dev/clang-static-analyzer/src/lib/dhcpsrv -resource-dir /usr/bin/../lib/clang/19 -D HAVE_CONFIG_H -I . -I ../../.. -I ../../../src/lib -I ../../../src/lib -D DHCP_DATA_DIR="/home/fedora/workspace/kea-dev/clang-static-analyzer/kea-bin/var/lib/kea" -D TOP_BUILDDIR="../../.." -D KEA_LFC_EXECUTABLE="/home/fedora/workspace/kea-dev/clang-static-analyzer/kea-bin/sbin/kea-lfc" -D OS_LINUX -I ../../.. -I ../../.. -D PIC -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../include/c++/14/backward -internal-isystem /usr/bin/../lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/14/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wwrite-strings -Wno-sign-compare -Wno-missing-field-initializers -std=c++20 -fdeprecated-macro -ferror-limit 19 -stack-protector 2 -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/fedora/workspace/kea-dev/clang-static-analyzer/report/2024-12-20-083036-19082-1 -x c++ parsers/host_reservation_parser.cc
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
19using namespace isc::asiolink;
20using namespace isc::data;
21
22namespace isc {
23namespace dhcp {
24
25namespace {
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).
35const std::set<std::string>&
36getSupportedParams4(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).
73const std::set<std::string>&
74getSupportedParams6(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.
107void
108parsePrefix(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
157HostPtr
158HostReservationParser::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
164HostPtr
165HostReservationParser::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
235bool
236HostReservationParser::isIdentifierParameter(const std::string& param_name) const {
237 return (getSupportedParameters(true).count(param_name) > 0);
238}
239
240bool
241HostReservationParser::isSupportedParameter(const std::string& param_name) const {
242 return (getSupportedParameters(false).count(param_name) > 0);
243}
244
245HostPtr
246HostReservationParser4::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
300const std::set<std::string>&
301HostReservationParser4::getSupportedParameters(const bool identifiers_only) const {
302 return (getSupportedParams4(identifiers_only));
303}
304
305HostPtr
306HostReservationParser6::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
412const std::set<std::string>&
413HostReservationParser6::getSupportedParameters(const bool identifiers_only) const {
414 return (getSupportedParams6(identifiers_only));
415}
416
417HostReservationIdsParser::HostReservationIdsParser()
418 : staging_cfg_() {
419}
420
421void
422HostReservationIdsParser::parse(isc::data::ConstElementPtr ids_list) {
423 parseInternal(ids_list);
424}
425
426void
427HostReservationIdsParser::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
479HostReservationIdsParser4::HostReservationIdsParser4()
480 : HostReservationIdsParser() {
481 staging_cfg_ = CfgMgr::instance().getStagingCfg()->getCfgHostOperations4();
482}
483
484bool
485HostReservationIdsParser4::isSupportedIdentifier(const std::string& id_name) const {
486 return (getSupportedParams4(true).count(id_name) > 0);
487}
488
489HostReservationIdsParser6::HostReservationIdsParser6()
490 : HostReservationIdsParser() {
491 staging_cfg_ = CfgMgr::instance().getStagingCfg()->getCfgHostOperations6();
492}
493
494bool
495HostReservationIdsParser6::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