Bug Summary

File:home/fedora/workspace/kea-dev/clang-static-analyzer/src/lib/dhcpsrv/parsers/dhcp_parsers.cc
Warning:line 927, column 13
Value stored to 'len' 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 dhcp_parsers.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/dhcp_parsers.cc
1// Copyright (C) 2013-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 <dhcp/iface_mgr.h>
9#include <dhcp/dhcp4.h>
10#include <dhcp/libdhcp++.h>
11#include <dhcpsrv/cfgmgr.h>
12#include <dhcpsrv/cfg_option.h>
13#include <dhcpsrv/dhcpsrv_log.h>
14#include <dhcpsrv/parsers/dhcp_parsers.h>
15#include <dhcpsrv/parsers/host_reservation_parser.h>
16#include <dhcpsrv/parsers/host_reservations_list_parser.h>
17#include <dhcpsrv/parsers/option_data_parser.h>
18#include <dhcpsrv/parsers/simple_parser4.h>
19#include <dhcpsrv/parsers/simple_parser6.h>
20#include <dhcpsrv/cfg_mac_source.h>
21#include <util/encode/encode.h>
22#include <util/str.h>
23
24#include <boost/algorithm/string.hpp>
25#include <boost/foreach.hpp>
26#include <boost/lexical_cast.hpp>
27#include <boost/make_shared.hpp>
28#include <boost/scoped_ptr.hpp>
29
30#include <limits>
31#include <map>
32#include <string>
33#include <vector>
34#include <iomanip>
35
36using namespace std;
37using namespace isc::asiolink;
38using namespace isc::data;
39using namespace isc::util;
40namespace ph = std::placeholders;
41
42namespace isc {
43namespace dhcp {
44
45// ******************** MACSourcesListConfigParser *************************
46
47void
48MACSourcesListConfigParser::parse(CfgMACSource& mac_sources, ConstElementPtr value) {
49 uint32_t source = 0;
50 size_t cnt = 0;
51
52 // By default, there's only one source defined: ANY.
53 // If user specified anything, we need to get rid of that default.
54 mac_sources.clear();
55
56 for (auto const& source_elem : value->listValue()) {
57 std::string source_str = source_elem->stringValue();
58 try {
59 source = CfgMACSource::MACSourceFromText(source_str);
60 mac_sources.add(source);
61 ++cnt;
62 } catch (const InvalidParameter& ex) {
63 isc_throw(DhcpConfigError, "The mac-sources value '" << source_strdo { std::ostringstream oss__; oss__ << "The mac-sources value '"
<< source_str << "' was specified twice (" <<
value->getPosition() << ")"; throw DhcpConfigError(
"parsers/dhcp_parsers.cc", 64, oss__.str().c_str()); } while (
1)
64 << "' was specified twice (" << value->getPosition() << ")")do { std::ostringstream oss__; oss__ << "The mac-sources value '"
<< source_str << "' was specified twice (" <<
value->getPosition() << ")"; throw DhcpConfigError(
"parsers/dhcp_parsers.cc", 64, oss__.str().c_str()); } while (
1)
;
65 } catch (const std::exception& ex) {
66 isc_throw(DhcpConfigError, "Failed to convert '"do { std::ostringstream oss__; oss__ << "Failed to convert '"
<< source_str << "' to any recognized MAC source:"
<< ex.what() << " (" << value->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 68, oss__.str().c_str()); } while (1)
67 << source_str << "' to any recognized MAC source:"do { std::ostringstream oss__; oss__ << "Failed to convert '"
<< source_str << "' to any recognized MAC source:"
<< ex.what() << " (" << value->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 68, oss__.str().c_str()); } while (1)
68 << ex.what() << " (" << value->getPosition() << ")")do { std::ostringstream oss__; oss__ << "Failed to convert '"
<< source_str << "' to any recognized MAC source:"
<< ex.what() << " (" << value->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 68, oss__.str().c_str()); } while (1)
;
69 }
70 }
71
72 if (!cnt) {
73 isc_throw(DhcpConfigError, "If specified, MAC Sources cannot be empty")do { std::ostringstream oss__; oss__ << "If specified, MAC Sources cannot be empty"
; throw DhcpConfigError("parsers/dhcp_parsers.cc", 73, oss__.
str().c_str()); } while (1)
;
74 }
75}
76
77// ******************** ControlSocketsParser *************************
78void ControlSocketsParser::parse(SrvConfig& srv_cfg, ConstElementPtr value) {
79 if (value->getType() != Element::list) {
80 // Sanity check: not supposed to fail.
81 isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "Specified control-sockets is expected to be a list"
; throw DhcpConfigError("parsers/dhcp_parsers.cc", 82, oss__.
str().c_str()); } while (1)
82 "Specified control-sockets is expected to be a list")do { std::ostringstream oss__; oss__ << "Specified control-sockets is expected to be a list"
; throw DhcpConfigError("parsers/dhcp_parsers.cc", 82, oss__.
str().c_str()); } while (1)
;
83 }
84 bool seen_unix(false);
85 bool seen_http(false);
86 for (ConstElementPtr socket : value->listValue()) {
87 if (socket->getType() != Element::map) {
88 // Sanity check: not supposed to fail.
89 isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "Specified control-sockets is expected to be a list of maps"
; throw DhcpConfigError("parsers/dhcp_parsers.cc", 90, oss__.
str().c_str()); } while (1)
90 "Specified control-sockets is expected to be a list of maps")do { std::ostringstream oss__; oss__ << "Specified control-sockets is expected to be a list of maps"
; throw DhcpConfigError("parsers/dhcp_parsers.cc", 90, oss__.
str().c_str()); } while (1)
;
91 }
92 ConstElementPtr socket_type = socket->get("socket-type");
93 if (!socket_type) {
94 isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "'socket-type' parameter is mandatory in control-sockets items"
; throw DhcpConfigError("parsers/dhcp_parsers.cc", 95, oss__.
str().c_str()); } while (1)
95 "'socket-type' parameter is mandatory in control-sockets items")do { std::ostringstream oss__; oss__ << "'socket-type' parameter is mandatory in control-sockets items"
; throw DhcpConfigError("parsers/dhcp_parsers.cc", 95, oss__.
str().c_str()); } while (1)
;
96 }
97 if (socket_type->getType() != Element::string) {
98 // Sanity check: not supposed to fail.
99 isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "'socket-type' parameter is expected to be a string"
; throw DhcpConfigError("parsers/dhcp_parsers.cc", 100, oss__
.str().c_str()); } while (1)
100 "'socket-type' parameter is expected to be a string")do { std::ostringstream oss__; oss__ << "'socket-type' parameter is expected to be a string"
; throw DhcpConfigError("parsers/dhcp_parsers.cc", 100, oss__
.str().c_str()); } while (1)
;
101 }
102 string type = socket_type->stringValue();
103 if (type == "unix") {
104 if (seen_unix) {
105 isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "control socket of type 'unix' already configured"
; throw DhcpConfigError("parsers/dhcp_parsers.cc", 106, oss__
.str().c_str()); } while (1)
106 "control socket of type 'unix' already configured")do { std::ostringstream oss__; oss__ << "control socket of type 'unix' already configured"
; throw DhcpConfigError("parsers/dhcp_parsers.cc", 106, oss__
.str().c_str()); } while (1)
;
107 }
108 seen_unix = true;
109 srv_cfg.setUnixControlSocketInfo(socket);
110 } else if ((type == "http") || (type == "https")) {
111 if (seen_http) {
112 isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "control socket of type 'http' or 'https'"
" already configured"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 114, oss__.str().c_str()); } while (1)
113 "control socket of type 'http' or 'https'"do { std::ostringstream oss__; oss__ << "control socket of type 'http' or 'https'"
" already configured"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 114, oss__.str().c_str()); } while (1)
114 " already configured")do { std::ostringstream oss__; oss__ << "control socket of type 'http' or 'https'"
" already configured"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 114, oss__.str().c_str()); } while (1)
;
115 }
116 seen_http = true;
117 using namespace isc::config;
118 HttpCommandConfigPtr http_config(new HttpCommandConfig(socket));
119 srv_cfg.setHttpControlSocketInfo(http_config);
120 } else {
121 // Sanity check: not supposed to fail.
122 isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "unsupported 'socket-type': '"
<< type << "' not 'unix', 'http' or 'https'"; throw
DhcpConfigError("parsers/dhcp_parsers.cc", 124, oss__.str().
c_str()); } while (1)
123 "unsupported 'socket-type': '" << typedo { std::ostringstream oss__; oss__ << "unsupported 'socket-type': '"
<< type << "' not 'unix', 'http' or 'https'"; throw
DhcpConfigError("parsers/dhcp_parsers.cc", 124, oss__.str().
c_str()); } while (1)
124 << "' not 'unix', 'http' or 'https'")do { std::ostringstream oss__; oss__ << "unsupported 'socket-type': '"
<< type << "' not 'unix', 'http' or 'https'"; throw
DhcpConfigError("parsers/dhcp_parsers.cc", 124, oss__.str().
c_str()); } while (1)
;
125 }
126 }
127}
128
129// ******************************** OptionDefParser ****************************
130
131OptionDefParser::OptionDefParser(const uint16_t address_family)
132 : address_family_(address_family) {
133}
134
135OptionDefinitionPtr
136OptionDefParser::parse(ConstElementPtr option_def) {
137
138 // Check parameters.
139 if (address_family_ == AF_INET2) {
140 checkKeywords(SimpleParser4::OPTION4_DEF_PARAMETERS, option_def);
141 } else {
142 checkKeywords(SimpleParser6::OPTION6_DEF_PARAMETERS, option_def);
143 }
144
145 // Get mandatory parameters.
146 std::string name = getString(option_def, "name");
147 int64_t code64 = getInteger(option_def, "code");
148 std::string type = getString(option_def, "type");
149
150 // Get optional parameters. Whoever called this parser, should have
151 // called SimpleParser::setDefaults first.
152 bool array_type = getBoolean(option_def, "array");
153 std::string record_types = getString(option_def, "record-types");
154 std::string space = getString(option_def, "space");
155 std::string encapsulates = getString(option_def, "encapsulate");
156 ConstElementPtr user_context = option_def->get("user-context");
157
158 // Check code value.
159 if (code64 < 0) {
160 isc_throw(DhcpConfigError, "option code must not be negative "do { std::ostringstream oss__; oss__ << "option code must not be negative "
"(" << getPosition("code", option_def) << ")"; throw
DhcpConfigError("parsers/dhcp_parsers.cc", 161, oss__.str().
c_str()); } while (1)
161 "(" << getPosition("code", option_def) << ")")do { std::ostringstream oss__; oss__ << "option code must not be negative "
"(" << getPosition("code", option_def) << ")"; throw
DhcpConfigError("parsers/dhcp_parsers.cc", 161, oss__.str().
c_str()); } while (1)
;
162 } else if (address_family_ == AF_INET2 &&
163 code64 > std::numeric_limits<uint8_t>::max()) {
164 isc_throw(DhcpConfigError, "invalid option code '" << code64do { std::ostringstream oss__; oss__ << "invalid option code '"
<< code64 << "', it must not be greater than '" <<
static_cast<int>(std::numeric_limits<uint8_t>::max
()) << "' (" << getPosition("code", option_def) <<
")"; throw DhcpConfigError("parsers/dhcp_parsers.cc", 167, oss__
.str().c_str()); } while (1)
165 << "', it must not be greater than '"do { std::ostringstream oss__; oss__ << "invalid option code '"
<< code64 << "', it must not be greater than '" <<
static_cast<int>(std::numeric_limits<uint8_t>::max
()) << "' (" << getPosition("code", option_def) <<
")"; throw DhcpConfigError("parsers/dhcp_parsers.cc", 167, oss__
.str().c_str()); } while (1)
166 << static_cast<int>(std::numeric_limits<uint8_t>::max())do { std::ostringstream oss__; oss__ << "invalid option code '"
<< code64 << "', it must not be greater than '" <<
static_cast<int>(std::numeric_limits<uint8_t>::max
()) << "' (" << getPosition("code", option_def) <<
")"; throw DhcpConfigError("parsers/dhcp_parsers.cc", 167, oss__
.str().c_str()); } while (1)
167 << "' (" << getPosition("code", option_def) << ")")do { std::ostringstream oss__; oss__ << "invalid option code '"
<< code64 << "', it must not be greater than '" <<
static_cast<int>(std::numeric_limits<uint8_t>::max
()) << "' (" << getPosition("code", option_def) <<
")"; throw DhcpConfigError("parsers/dhcp_parsers.cc", 167, oss__
.str().c_str()); } while (1)
;
168 } else if (address_family_ == AF_INET610 &&
169 code64 > std::numeric_limits<uint16_t>::max()) {
170 isc_throw(DhcpConfigError, "invalid option code '" << code64do { std::ostringstream oss__; oss__ << "invalid option code '"
<< code64 << "', it must not be greater than '" <<
std::numeric_limits<uint16_t>::max() << "' (" <<
getPosition("code", option_def) << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 173, oss__.str().c_str()); } while
(1)
171 << "', it must not be greater than '"do { std::ostringstream oss__; oss__ << "invalid option code '"
<< code64 << "', it must not be greater than '" <<
std::numeric_limits<uint16_t>::max() << "' (" <<
getPosition("code", option_def) << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 173, oss__.str().c_str()); } while
(1)
172 << std::numeric_limits<uint16_t>::max()do { std::ostringstream oss__; oss__ << "invalid option code '"
<< code64 << "', it must not be greater than '" <<
std::numeric_limits<uint16_t>::max() << "' (" <<
getPosition("code", option_def) << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 173, oss__.str().c_str()); } while
(1)
173 << "' (" << getPosition("code", option_def) << ")")do { std::ostringstream oss__; oss__ << "invalid option code '"
<< code64 << "', it must not be greater than '" <<
std::numeric_limits<uint16_t>::max() << "' (" <<
getPosition("code", option_def) << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 173, oss__.str().c_str()); } while
(1)
;
174 }
175 uint32_t code = static_cast<uint32_t>(code64);
176
177 // Validate space name.
178 if (!OptionSpace::validateName(space)) {
179 isc_throw(DhcpConfigError, "invalid option space name '"do { std::ostringstream oss__; oss__ << "invalid option space name '"
<< space << "' (" << getPosition("space", option_def
) << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 181, oss__.str().c_str()); } while (1)
180 << space << "' ("do { std::ostringstream oss__; oss__ << "invalid option space name '"
<< space << "' (" << getPosition("space", option_def
) << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 181, oss__.str().c_str()); } while (1)
181 << getPosition("space", option_def) << ")")do { std::ostringstream oss__; oss__ << "invalid option space name '"
<< space << "' (" << getPosition("space", option_def
) << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 181, oss__.str().c_str()); } while (1)
;
182 }
183
184 // Protect against definition of options 0 (PAD) or 255 (END)
185 // in (and only in) the dhcp4 space.
186 if (space == DHCP4_OPTION_SPACE"dhcp4") {
187 if (code == DHO_PAD) {
188 isc_throw(DhcpConfigError, "invalid option code '0': "do { std::ostringstream oss__; oss__ << "invalid option code '0': "
<< "reserved for PAD (" << getPosition("code", option_def
) << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 190, oss__.str().c_str()); } while (1)
189 << "reserved for PAD ("do { std::ostringstream oss__; oss__ << "invalid option code '0': "
<< "reserved for PAD (" << getPosition("code", option_def
) << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 190, oss__.str().c_str()); } while (1)
190 << getPosition("code", option_def) << ")")do { std::ostringstream oss__; oss__ << "invalid option code '0': "
<< "reserved for PAD (" << getPosition("code", option_def
) << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 190, oss__.str().c_str()); } while (1)
;
191 } else if (code == DHO_END) {
192 isc_throw(DhcpConfigError, "invalid option code '255': "do { std::ostringstream oss__; oss__ << "invalid option code '255': "
<< "reserved for END (" << getPosition("code", option_def
) << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 194, oss__.str().c_str()); } while (1)
193 << "reserved for END ("do { std::ostringstream oss__; oss__ << "invalid option code '255': "
<< "reserved for END (" << getPosition("code", option_def
) << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 194, oss__.str().c_str()); } while (1)
194 << getPosition("code", option_def) << ")")do { std::ostringstream oss__; oss__ << "invalid option code '255': "
<< "reserved for END (" << getPosition("code", option_def
) << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 194, oss__.str().c_str()); } while (1)
;
195 }
196 }
197
198 // For dhcp6 space the value 0 is reserved.
199 if (space == DHCP6_OPTION_SPACE"dhcp6") {
200 if (code == 0) {
201 isc_throw(DhcpConfigError, "invalid option code '0': "do { std::ostringstream oss__; oss__ << "invalid option code '0': "
<< "reserved value (" << getPosition("code", option_def
) << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 203, oss__.str().c_str()); } while (1)
202 << "reserved value ("do { std::ostringstream oss__; oss__ << "invalid option code '0': "
<< "reserved value (" << getPosition("code", option_def
) << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 203, oss__.str().c_str()); } while (1)
203 << getPosition("code", option_def) << ")")do { std::ostringstream oss__; oss__ << "invalid option code '0': "
<< "reserved value (" << getPosition("code", option_def
) << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 203, oss__.str().c_str()); } while (1)
;
204 }
205 }
206
207 // Create option definition.
208 OptionDefinitionPtr def;
209 // We need to check if user has set encapsulated option space
210 // name. If so, different constructor will be used.
211 if (!encapsulates.empty()) {
212 // Arrays can't be used together with sub-options.
213 if (array_type) {
214 isc_throw(DhcpConfigError, "option '" << space << "."do { std::ostringstream oss__; oss__ << "option '" <<
space << "." << name << "', comprising an array of data"
<< " fields may not encapsulate any option space (" <<
option_def->getPosition() << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 217, oss__.str().c_str()); } while
(1)
215 << name << "', comprising an array of data"do { std::ostringstream oss__; oss__ << "option '" <<
space << "." << name << "', comprising an array of data"
<< " fields may not encapsulate any option space (" <<
option_def->getPosition() << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 217, oss__.str().c_str()); } while
(1)
216 << " fields may not encapsulate any option space ("do { std::ostringstream oss__; oss__ << "option '" <<
space << "." << name << "', comprising an array of data"
<< " fields may not encapsulate any option space (" <<
option_def->getPosition() << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 217, oss__.str().c_str()); } while
(1)
217 << option_def->getPosition() << ")")do { std::ostringstream oss__; oss__ << "option '" <<
space << "." << name << "', comprising an array of data"
<< " fields may not encapsulate any option space (" <<
option_def->getPosition() << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 217, oss__.str().c_str()); } while
(1)
;
218
219 } else if (encapsulates == space) {
220 isc_throw(DhcpConfigError, "option must not encapsulate"do { std::ostringstream oss__; oss__ << "option must not encapsulate"
<< " an option space it belongs to: '" << space <<
"." << name << "' is set to" << " encapsulate '"
<< space << "' (" << option_def->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 224, oss__.str().c_str()); } while (1)
221 << " an option space it belongs to: '"do { std::ostringstream oss__; oss__ << "option must not encapsulate"
<< " an option space it belongs to: '" << space <<
"." << name << "' is set to" << " encapsulate '"
<< space << "' (" << option_def->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 224, oss__.str().c_str()); } while (1)
222 << space << "." << name << "' is set to"do { std::ostringstream oss__; oss__ << "option must not encapsulate"
<< " an option space it belongs to: '" << space <<
"." << name << "' is set to" << " encapsulate '"
<< space << "' (" << option_def->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 224, oss__.str().c_str()); } while (1)
223 << " encapsulate '" << space << "' ("do { std::ostringstream oss__; oss__ << "option must not encapsulate"
<< " an option space it belongs to: '" << space <<
"." << name << "' is set to" << " encapsulate '"
<< space << "' (" << option_def->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 224, oss__.str().c_str()); } while (1)
224 << option_def->getPosition() << ")")do { std::ostringstream oss__; oss__ << "option must not encapsulate"
<< " an option space it belongs to: '" << space <<
"." << name << "' is set to" << " encapsulate '"
<< space << "' (" << option_def->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 224, oss__.str().c_str()); } while (1)
;
225
226 } else {
227 def.reset(new OptionDefinition(name, code, space, type,
228 encapsulates.c_str()));
229 }
230
231 } else {
232 def.reset(new OptionDefinition(name, code, space, type, array_type));
233
234 }
235
236 if (user_context) {
237 def->setContext(user_context);
238 }
239
240 // Split the list of record types into tokens.
241 std::vector<std::string> record_tokens =
242 isc::util::str::tokens(record_types, ",");
243 // Iterate over each token and add a record type into
244 // option definition.
245 for (auto const& record_type : record_tokens) {
246 try {
247 auto const trim_rec = boost::trim_copy(record_type);
248 if (!trim_rec.empty()) {
249 def->addRecordField(trim_rec);
250 }
251 } catch (const Exception& ex) {
252 isc_throw(DhcpConfigError, "invalid record type values"do { std::ostringstream oss__; oss__ << "invalid record type values"
<< " specified for the option definition: " << ex
.what() << " (" << getPosition("record-types", option_def
) << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 255, oss__.str().c_str()); } while (1)
253 << " specified for the option definition: "do { std::ostringstream oss__; oss__ << "invalid record type values"
<< " specified for the option definition: " << ex
.what() << " (" << getPosition("record-types", option_def
) << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 255, oss__.str().c_str()); } while (1)
254 << ex.what() << " ("do { std::ostringstream oss__; oss__ << "invalid record type values"
<< " specified for the option definition: " << ex
.what() << " (" << getPosition("record-types", option_def
) << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 255, oss__.str().c_str()); } while (1)
255 << getPosition("record-types", option_def) << ")")do { std::ostringstream oss__; oss__ << "invalid record type values"
<< " specified for the option definition: " << ex
.what() << " (" << getPosition("record-types", option_def
) << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 255, oss__.str().c_str()); } while (1)
;
256 }
257 }
258
259 // Validate the definition.
260 try {
261 def->validate();
262 } catch (const std::exception& ex) {
263 isc_throw(DhcpConfigError, ex.what()do { std::ostringstream oss__; oss__ << ex.what() <<
" (" << option_def->getPosition() << ")"; throw
DhcpConfigError("parsers/dhcp_parsers.cc", 264, oss__.str().
c_str()); } while (1)
264 << " (" << option_def->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() <<
" (" << option_def->getPosition() << ")"; throw
DhcpConfigError("parsers/dhcp_parsers.cc", 264, oss__.str().
c_str()); } while (1)
;
265 }
266
267 // Option definition has been created successfully.
268 return (def);
269}
270
271// ******************************** OptionDefListParser ************************
272
273OptionDefListParser::OptionDefListParser(const uint16_t address_family)
274 : address_family_(address_family) {
275}
276
277void
278OptionDefListParser::parse(CfgOptionDefPtr storage, ConstElementPtr option_def_list) {
279 if (!option_def_list) {
280 // Sanity check: not supposed to fail.
281 isc_throw(DhcpConfigError, "parser error: a pointer to a list of"do { std::ostringstream oss__; oss__ << "parser error: a pointer to a list of"
<< " option definitions is NULL (" << option_def_list
->getPosition() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 283, oss__.str().c_str()); } while (1)
282 << " option definitions is NULL ("do { std::ostringstream oss__; oss__ << "parser error: a pointer to a list of"
<< " option definitions is NULL (" << option_def_list
->getPosition() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 283, oss__.str().c_str()); } while (1)
283 << option_def_list->getPosition() << ")")do { std::ostringstream oss__; oss__ << "parser error: a pointer to a list of"
<< " option definitions is NULL (" << option_def_list
->getPosition() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 283, oss__.str().c_str()); } while (1)
;
284 }
285
286 OptionDefParser parser(address_family_);
287 for (auto const& option_def : option_def_list->listValue()) {
288 OptionDefinitionPtr def = parser.parse(option_def);
289 try {
290 storage->add(def);
291 } catch (const std::exception& ex) {
292 // Append position if there is a failure.
293 isc_throw(DhcpConfigError, ex.what() << " ("do { std::ostringstream oss__; oss__ << ex.what() <<
" (" << option_def->getPosition() << ")"; throw
DhcpConfigError("parsers/dhcp_parsers.cc", 294, oss__.str().
c_str()); } while (1)
294 << option_def->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() <<
" (" << option_def->getPosition() << ")"; throw
DhcpConfigError("parsers/dhcp_parsers.cc", 294, oss__.str().
c_str()); } while (1)
;
295 }
296 }
297
298 // All definitions have been prepared. Put them as runtime options into
299 // the libdhcp++.
300 LibDHCP::setRuntimeOptionDefs(storage->getContainer());
301}
302
303//****************************** RelayInfoParser ********************************
304RelayInfoParser::RelayInfoParser(const Option::Universe& family)
305 : family_(family) {
306};
307
308void
309RelayInfoParser::parse(const isc::dhcp::Network::RelayInfoPtr& relay_info,
310 ConstElementPtr relay_elem) {
311
312 if (relay_elem->getType() != Element::map) {
313 isc_throw(DhcpConfigError, "relay must be a map")do { std::ostringstream oss__; oss__ << "relay must be a map"
; throw DhcpConfigError("parsers/dhcp_parsers.cc", 313, oss__
.str().c_str()); } while (1)
;
314 }
315
316 ConstElementPtr addresses = relay_elem->get("ip-addresses");
317 if (!addresses) {
318 isc_throw(DhcpConfigError, "ip-addresses is required")do { std::ostringstream oss__; oss__ << "ip-addresses is required"
; throw DhcpConfigError("parsers/dhcp_parsers.cc", 318, oss__
.str().c_str()); } while (1)
;
319 }
320
321 // Create our resultant RelayInfo structure
322 *relay_info = isc::dhcp::Network::RelayInfo();
323
324 if (addresses->getType() != Element::list) {
325 isc_throw(DhcpConfigError, "ip-addresses must be a list "do { std::ostringstream oss__; oss__ << "ip-addresses must be a list "
"(" << getPosition("ip-addresses", relay_elem) <<
")"; throw DhcpConfigError("parsers/dhcp_parsers.cc", 326, oss__
.str().c_str()); } while (1)
326 "(" << getPosition("ip-addresses", relay_elem) << ")")do { std::ostringstream oss__; oss__ << "ip-addresses must be a list "
"(" << getPosition("ip-addresses", relay_elem) <<
")"; throw DhcpConfigError("parsers/dhcp_parsers.cc", 326, oss__
.str().c_str()); } while (1)
;
327 }
328
329 for (auto const& address_element : addresses->listValue()) {
330 addAddress("ip-addresses", address_element->stringValue(),
331 relay_elem, relay_info);
332 }
333}
334
335void
336RelayInfoParser::addAddress(const std::string& name,
337 const std::string& address_str,
338 ConstElementPtr relay_elem,
339 const isc::dhcp::Network::RelayInfoPtr& relay_info) {
340 boost::scoped_ptr<isc::asiolink::IOAddress> ip;
341 try {
342 ip.reset(new isc::asiolink::IOAddress(address_str));
343 } catch (const std::exception& ex) {
344 isc_throw(DhcpConfigError, "address " << address_strdo { std::ostringstream oss__; oss__ << "address " <<
address_str << " is not a valid: " << (family_ ==
Option::V4 ? "IPv4" : "IPv6") << "address" << " ("
<< getPosition(name, relay_elem) << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 348, oss__.str().c_str()); } while
(1)
345 << " is not a valid: "do { std::ostringstream oss__; oss__ << "address " <<
address_str << " is not a valid: " << (family_ ==
Option::V4 ? "IPv4" : "IPv6") << "address" << " ("
<< getPosition(name, relay_elem) << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 348, oss__.str().c_str()); } while
(1)
346 << (family_ == Option::V4 ? "IPv4" : "IPv6")do { std::ostringstream oss__; oss__ << "address " <<
address_str << " is not a valid: " << (family_ ==
Option::V4 ? "IPv4" : "IPv6") << "address" << " ("
<< getPosition(name, relay_elem) << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 348, oss__.str().c_str()); } while
(1)
347 << "address"do { std::ostringstream oss__; oss__ << "address " <<
address_str << " is not a valid: " << (family_ ==
Option::V4 ? "IPv4" : "IPv6") << "address" << " ("
<< getPosition(name, relay_elem) << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 348, oss__.str().c_str()); } while
(1)
348 << " (" << getPosition(name, relay_elem) << ")")do { std::ostringstream oss__; oss__ << "address " <<
address_str << " is not a valid: " << (family_ ==
Option::V4 ? "IPv4" : "IPv6") << "address" << " ("
<< getPosition(name, relay_elem) << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 348, oss__.str().c_str()); } while
(1)
;
349 }
350
351 // Check if the address family matches.
352 if ((ip->isV4() && family_ != Option::V4) ||
353 (ip->isV6() && family_ != Option::V6) ) {
354 isc_throw(DhcpConfigError, "address " << address_strdo { std::ostringstream oss__; oss__ << "address " <<
address_str << " is not a: " << (family_ == Option
::V4 ? "IPv4" : "IPv6") << "address" << " (" <<
getPosition(name, relay_elem) << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 358, oss__.str().c_str()); } while
(1)
355 << " is not a: "do { std::ostringstream oss__; oss__ << "address " <<
address_str << " is not a: " << (family_ == Option
::V4 ? "IPv4" : "IPv6") << "address" << " (" <<
getPosition(name, relay_elem) << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 358, oss__.str().c_str()); } while
(1)
356 << (family_ == Option::V4 ? "IPv4" : "IPv6")do { std::ostringstream oss__; oss__ << "address " <<
address_str << " is not a: " << (family_ == Option
::V4 ? "IPv4" : "IPv6") << "address" << " (" <<
getPosition(name, relay_elem) << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 358, oss__.str().c_str()); } while
(1)
357 << "address"do { std::ostringstream oss__; oss__ << "address " <<
address_str << " is not a: " << (family_ == Option
::V4 ? "IPv4" : "IPv6") << "address" << " (" <<
getPosition(name, relay_elem) << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 358, oss__.str().c_str()); } while
(1)
358 << " (" << getPosition(name, relay_elem) << ")")do { std::ostringstream oss__; oss__ << "address " <<
address_str << " is not a: " << (family_ == Option
::V4 ? "IPv4" : "IPv6") << "address" << " (" <<
getPosition(name, relay_elem) << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 358, oss__.str().c_str()); } while
(1)
;
359 }
360
361 try {
362 relay_info->addAddress(*ip);
363 } catch (const std::exception& ex) {
364 isc_throw(DhcpConfigError, "cannot add address: " << address_strdo { std::ostringstream oss__; oss__ << "cannot add address: "
<< address_str << " to relay info: " << ex
.what() << " (" << getPosition(name, relay_elem) <<
")"; throw DhcpConfigError("parsers/dhcp_parsers.cc", 366, oss__
.str().c_str()); } while (1)
365 << " to relay info: " << ex.what()do { std::ostringstream oss__; oss__ << "cannot add address: "
<< address_str << " to relay info: " << ex
.what() << " (" << getPosition(name, relay_elem) <<
")"; throw DhcpConfigError("parsers/dhcp_parsers.cc", 366, oss__
.str().c_str()); } while (1)
366 << " (" << getPosition(name, relay_elem) << ")")do { std::ostringstream oss__; oss__ << "cannot add address: "
<< address_str << " to relay info: " << ex
.what() << " (" << getPosition(name, relay_elem) <<
")"; throw DhcpConfigError("parsers/dhcp_parsers.cc", 366, oss__
.str().c_str()); } while (1)
;
367 }
368}
369
370//****************************** PoolParser ********************************
371
372void
373PoolParser::parse(PoolStoragePtr pools,
374 ConstElementPtr pool_structure,
375 const uint16_t address_family,
376 bool encapsulate_options) {
377
378 if (address_family == AF_INET2) {
379 checkKeywords(SimpleParser4::POOL4_PARAMETERS, pool_structure);
380 } else {
381 checkKeywords(SimpleParser6::POOL6_PARAMETERS, pool_structure);
382 }
383
384 ConstElementPtr text_pool = pool_structure->get("pool");
385
386 if (!text_pool) {
387 isc_throw(DhcpConfigError, "Mandatory 'pool' entry missing in "do { std::ostringstream oss__; oss__ << "Mandatory 'pool' entry missing in "
"definition: (" << pool_structure->getPosition() <<
")"; throw DhcpConfigError("parsers/dhcp_parsers.cc", 388, oss__
.str().c_str()); } while (1)
388 "definition: (" << pool_structure->getPosition() << ")")do { std::ostringstream oss__; oss__ << "Mandatory 'pool' entry missing in "
"definition: (" << pool_structure->getPosition() <<
")"; throw DhcpConfigError("parsers/dhcp_parsers.cc", 388, oss__
.str().c_str()); } while (1)
;
389 }
390
391 // That should be a single pool representation. It should contain
392 // text is form prefix/len or first - last. Note that spaces
393 // are allowed
394 string txt = text_pool->stringValue();
395
396 // first let's remove any whitespaces
397 boost::erase_all(txt, " "); // space
398 boost::erase_all(txt, "\t"); // tabulation
399
400 PoolPtr pool;
401
402 // Is this prefix/len notation?
403 size_t pos = txt.find("/");
404 if (pos != string::npos) {
405 isc::asiolink::IOAddress addr("::");
406 uint8_t len = 0;
407 try {
408 addr = isc::asiolink::IOAddress(txt.substr(0, pos));
409
410 // start with the first character after /
411 string prefix_len = txt.substr(pos + 1);
412
413 // It is lexical cast to int and then downcast to uint8_t.
414 // Direct cast to uint8_t (which is really an unsigned char)
415 // will result in interpreting the first digit as output
416 // value and throwing exception if length is written on two
417 // digits (because there are extra characters left over).
418
419 // No checks for values over 128. Range correctness will
420 // be checked in Pool4 constructor, here we only check
421 // the representation fits in an uint8_t as this can't
422 // be done by a direct lexical cast as explained...
423 int val_len = boost::lexical_cast<int>(prefix_len);
424 if ((val_len < std::numeric_limits<uint8_t>::min()) ||
425 (val_len > std::numeric_limits<uint8_t>::max())) {
426 // This exception will be handled 4 line later!
427 isc_throw(OutOfRange, "")do { std::ostringstream oss__; oss__ << ""; throw OutOfRange
("parsers/dhcp_parsers.cc", 427, oss__.str().c_str()); } while
(1)
;
428 }
429 len = static_cast<uint8_t>(val_len);
430 } catch (...) {
431 isc_throw(DhcpConfigError, "Failed to parse pool "do { std::ostringstream oss__; oss__ << "Failed to parse pool "
"definition: " << txt << " (" << text_pool
->getPosition() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 433, oss__.str().c_str()); } while (1)
432 "definition: " << txt << " ("do { std::ostringstream oss__; oss__ << "Failed to parse pool "
"definition: " << txt << " (" << text_pool
->getPosition() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 433, oss__.str().c_str()); } while (1)
433 << text_pool->getPosition() << ")")do { std::ostringstream oss__; oss__ << "Failed to parse pool "
"definition: " << txt << " (" << text_pool
->getPosition() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 433, oss__.str().c_str()); } while (1)
;
434 }
435
436 try {
437 pool = poolMaker(addr, len);
438 pools->push_back(pool);
439 } catch (const std::exception& ex) {
440 isc_throw(DhcpConfigError, "Failed to create pool defined by: "do { std::ostringstream oss__; oss__ << "Failed to create pool defined by: "
<< txt << " (" << text_pool->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 441, oss__.str().c_str()); } while (1)
441 << txt << " (" << text_pool->getPosition() << ")")do { std::ostringstream oss__; oss__ << "Failed to create pool defined by: "
<< txt << " (" << text_pool->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 441, oss__.str().c_str()); } while (1)
;
442 }
443
444 } else {
445 isc::asiolink::IOAddress min("::");
446 isc::asiolink::IOAddress max("::");
447
448 // Is this min-max notation?
449 pos = txt.find("-");
450 if (pos != string::npos) {
451 // using min-max notation
452 try {
453 min = isc::asiolink::IOAddress(txt.substr(0, pos));
454 max = isc::asiolink::IOAddress(txt.substr(pos + 1));
455 } catch (...) {
456 isc_throw(DhcpConfigError, "Failed to parse pool "do { std::ostringstream oss__; oss__ << "Failed to parse pool "
"definition: " << txt << " (" << text_pool
->getPosition() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 458, oss__.str().c_str()); } while (1)
457 "definition: " << txt << " ("do { std::ostringstream oss__; oss__ << "Failed to parse pool "
"definition: " << txt << " (" << text_pool
->getPosition() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 458, oss__.str().c_str()); } while (1)
458 << text_pool->getPosition() << ")")do { std::ostringstream oss__; oss__ << "Failed to parse pool "
"definition: " << txt << " (" << text_pool
->getPosition() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 458, oss__.str().c_str()); } while (1)
;
459 }
460
461 try {
462 pool = poolMaker(min, max);
463 pools->push_back(pool);
464 } catch (const std::exception& ex) {
465 isc_throw(DhcpConfigError, "Failed to create pool defined by: "do { std::ostringstream oss__; oss__ << "Failed to create pool defined by: "
<< txt << " (" << text_pool->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 466, oss__.str().c_str()); } while (1)
466 << txt << " (" << text_pool->getPosition() << ")")do { std::ostringstream oss__; oss__ << "Failed to create pool defined by: "
<< txt << " (" << text_pool->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 466, oss__.str().c_str()); } while (1)
;
467 }
468 }
469 }
470
471 if (!pool) {
472 isc_throw(DhcpConfigError, "invalid pool definition: "do { std::ostringstream oss__; oss__ << "invalid pool definition: "
<< text_pool->stringValue() << ". There are two acceptable formats <min address-max address>"
" or <prefix/len> (" << text_pool->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 476, oss__.str().c_str()); } while (1)
473 << text_pool->stringValue() <<do { std::ostringstream oss__; oss__ << "invalid pool definition: "
<< text_pool->stringValue() << ". There are two acceptable formats <min address-max address>"
" or <prefix/len> (" << text_pool->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 476, oss__.str().c_str()); } while (1)
474 ". There are two acceptable formats <min address-max address>"do { std::ostringstream oss__; oss__ << "invalid pool definition: "
<< text_pool->stringValue() << ". There are two acceptable formats <min address-max address>"
" or <prefix/len> (" << text_pool->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 476, oss__.str().c_str()); } while (1)
475 " or <prefix/len> ("do { std::ostringstream oss__; oss__ << "invalid pool definition: "
<< text_pool->stringValue() << ". There are two acceptable formats <min address-max address>"
" or <prefix/len> (" << text_pool->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 476, oss__.str().c_str()); } while (1)
476 << text_pool->getPosition() << ")")do { std::ostringstream oss__; oss__ << "invalid pool definition: "
<< text_pool->stringValue() << ". There are two acceptable formats <min address-max address>"
" or <prefix/len> (" << text_pool->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 476, oss__.str().c_str()); } while (1)
;
477 }
478
479 // If there is a pool-id, store it.
480 ConstElementPtr pool_id = pool_structure->get("pool-id");
481 if (pool_id) {
482 if (pool_id->intValue() <= 0) {
483 isc_throw(BadValue, "pool-id " << pool_id->intValue() << " is not"do { std::ostringstream oss__; oss__ << "pool-id " <<
pool_id->intValue() << " is not" << " a positive integer greater than 0"
; throw BadValue("parsers/dhcp_parsers.cc", 484, oss__.str().
c_str()); } while (1)
484 << " a positive integer greater than 0")do { std::ostringstream oss__; oss__ << "pool-id " <<
pool_id->intValue() << " is not" << " a positive integer greater than 0"
; throw BadValue("parsers/dhcp_parsers.cc", 484, oss__.str().
c_str()); } while (1)
;
485 } else if (pool_id->intValue() > numeric_limits<uint32_t>::max()) {
486 isc_throw(BadValue, "pool-id " << pool_id->intValue() << " is not"do { std::ostringstream oss__; oss__ << "pool-id " <<
pool_id->intValue() << " is not" << " a 32 bit unsigned integer"
; throw BadValue("parsers/dhcp_parsers.cc", 487, oss__.str().
c_str()); } while (1)
487 << " a 32 bit unsigned integer")do { std::ostringstream oss__; oss__ << "pool-id " <<
pool_id->intValue() << " is not" << " a 32 bit unsigned integer"
; throw BadValue("parsers/dhcp_parsers.cc", 487, oss__.str().
c_str()); } while (1)
;
488 }
489
490 pool->setID(pool_id->intValue());
491 }
492
493 // If there's user-context specified, store it.
494 ConstElementPtr user_context = pool_structure->get("user-context");
495 if (user_context) {
496 // The grammar accepts only maps but still check it.
497 if (user_context->getType() != Element::map) {
498 isc_throw(isc::dhcp::DhcpConfigError, "User context has to be a map ("do { std::ostringstream oss__; oss__ << "User context has to be a map ("
<< user_context->getPosition() << ")"; throw isc
::dhcp::DhcpConfigError("parsers/dhcp_parsers.cc", 499, oss__
.str().c_str()); } while (1)
499 << user_context->getPosition() << ")")do { std::ostringstream oss__; oss__ << "User context has to be a map ("
<< user_context->getPosition() << ")"; throw isc
::dhcp::DhcpConfigError("parsers/dhcp_parsers.cc", 499, oss__
.str().c_str()); } while (1)
;
500 }
501 pool->setContext(user_context);
502 }
503
504 // Parser pool specific options.
505 ConstElementPtr option_data = pool_structure->get("option-data");
506 if (option_data) {
507 try {
508 CfgOptionPtr cfg = pool->getCfgOption();
509 auto option_parser = createOptionDataListParser(address_family);
510 option_parser->parse(cfg, option_data, encapsulate_options);
511 } catch (const std::exception& ex) {
512 isc_throw(isc::dhcp::DhcpConfigError, ex.what()do { std::ostringstream oss__; oss__ << ex.what() <<
" (" << option_data->getPosition() << ")"; throw
isc::dhcp::DhcpConfigError("parsers/dhcp_parsers.cc", 513, oss__
.str().c_str()); } while (1)
513 << " (" << option_data->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() <<
" (" << option_data->getPosition() << ")"; throw
isc::dhcp::DhcpConfigError("parsers/dhcp_parsers.cc", 513, oss__
.str().c_str()); } while (1)
;
514 }
515 }
516
517 // Client-class.
518 ConstElementPtr client_class = pool_structure->get("client-class");
519 if (client_class) {
520 string cclass = client_class->stringValue();
521 if (!cclass.empty()) {
522 pool->allowClientClass(cclass);
523 }
524 }
525
526 // Setup client class list.
527 BaseNetworkParser::getClientClassesElem(pool_structure,
528 std::bind(&Pool::allowClientClass,
529 pool, ph::_1));
530
531 // Setup additional class list.
532 BaseNetworkParser::getAdditionalClassesElem(pool_structure,
533 std::bind(&Pool::addAdditionalClass,
534 pool, ph::_1));
535}
536
537boost::shared_ptr<OptionDataListParser>
538PoolParser::createOptionDataListParser(const uint16_t address_family) const {
539 return (boost::make_shared<OptionDataListParser>(address_family));
540}
541
542//****************************** Pool4Parser *************************
543
544PoolPtr
545Pool4Parser::poolMaker (IOAddress &addr, uint32_t len, int32_t) {
546 return (PoolPtr(new Pool4(addr, len)));
547}
548
549PoolPtr
550Pool4Parser::poolMaker (IOAddress &min, IOAddress &max, int32_t) {
551 return (PoolPtr(new Pool4(min, max)));
552}
553
554//****************************** Pools4ListParser *************************
555
556void
557Pools4ListParser::parse(PoolStoragePtr pools, ConstElementPtr pools_list,
558 bool encapsulate_options) {
559 for (auto const& pool : pools_list->listValue()) {
560 auto const& parser = createPoolConfigParser();
561 parser->parse(pools, pool, AF_INET2, encapsulate_options);
562 }
563}
564
565boost::shared_ptr<PoolParser>
566Pools4ListParser::createPoolConfigParser() const {
567 return (boost::make_shared<Pool4Parser>());
568}
569
570//****************************** SubnetConfigParser *************************
571
572SubnetConfigParser::SubnetConfigParser(uint16_t family, bool check_iface)
573 : pools_(new PoolStorage()),
574 address_family_(family),
575 check_iface_(check_iface) {
576 relay_info_.reset(new isc::dhcp::Network::RelayInfo());
577}
578
579SubnetPtr
580SubnetConfigParser::parse(ConstElementPtr subnet, bool encapsulate_options) {
581
582 ConstElementPtr relay_params = subnet->get("relay");
583 if (relay_params) {
584 Option::Universe u = (address_family_ == AF_INET2) ? Option::V4 : Option::V6;
585 RelayInfoParser parser(u);
586 parser.parse(relay_info_, relay_params);
587 }
588
589 // Create a subnet.
590 try {
591 createSubnet(subnet);
592 } catch (const std::exception& ex) {
593 isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "subnet configuration failed: "
<< ex.what(); throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 594, oss__.str().c_str()); } while (1)
594 "subnet configuration failed: " << ex.what())do { std::ostringstream oss__; oss__ << "subnet configuration failed: "
<< ex.what(); throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 594, oss__.str().c_str()); } while (1)
;
595 }
596
597 // We create subnet first and then parse the options straight into the subnet's
598 // CfgOption structure. Previously, we first parsed the options and then copied
599 // them into the CfgOption after creating the subnet but it had two issues. First,
600 // it cost performance. Second, copying options reset the isEncapsulated() flag.
601 // If the options have been encapsulated we want to preserve the flag to ensure
602 // they are not encapsulated several times.
603 ConstElementPtr options_params = subnet->get("option-data");
604 if (options_params) {
605 auto opt_parser = createOptionDataListParser();
606 opt_parser->parse(subnet_->getCfgOption(), options_params, encapsulate_options);
607 }
608
609 return (subnet_);
610}
611
612void
613SubnetConfigParser::createSubnet(ConstElementPtr params) {
614 std::string subnet_txt;
615 try {
616 subnet_txt = getString(params, "subnet");
617 } catch (const DhcpConfigError &) {
618 // rethrow with precise error
619 isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "mandatory 'subnet' parameter is missing for a subnet being"
" configured (" << params->getPosition() << ")"
; throw DhcpConfigError("parsers/dhcp_parsers.cc", 621, oss__
.str().c_str()); } while (1)
620 "mandatory 'subnet' parameter is missing for a subnet being"do { std::ostringstream oss__; oss__ << "mandatory 'subnet' parameter is missing for a subnet being"
" configured (" << params->getPosition() << ")"
; throw DhcpConfigError("parsers/dhcp_parsers.cc", 621, oss__
.str().c_str()); } while (1)
621 " configured (" << params->getPosition() << ")")do { std::ostringstream oss__; oss__ << "mandatory 'subnet' parameter is missing for a subnet being"
" configured (" << params->getPosition() << ")"
; throw DhcpConfigError("parsers/dhcp_parsers.cc", 621, oss__
.str().c_str()); } while (1)
;
622 }
623
624 // Remove any spaces or tabs.
625 boost::erase_all(subnet_txt, " ");
626 boost::erase_all(subnet_txt, "\t");
627
628 // The subnet format is prefix/len. We are going to extract
629 // the prefix portion of a subnet string to create IOAddress
630 // object from it. IOAddress will be passed to the Subnet's
631 // constructor later on. In order to extract the prefix we
632 // need to get all characters preceding "/".
633 size_t pos = subnet_txt.find("/");
634 if (pos == string::npos) {
635 ConstElementPtr elem = params->get("subnet");
636 isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "Invalid subnet syntax (prefix/len expected):"
<< subnet_txt << " (" << elem->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 638, oss__.str().c_str()); } while (1)
637 "Invalid subnet syntax (prefix/len expected):" << subnet_txtdo { std::ostringstream oss__; oss__ << "Invalid subnet syntax (prefix/len expected):"
<< subnet_txt << " (" << elem->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 638, oss__.str().c_str()); } while (1)
638 << " (" << elem->getPosition() << ")")do { std::ostringstream oss__; oss__ << "Invalid subnet syntax (prefix/len expected):"
<< subnet_txt << " (" << elem->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 638, oss__.str().c_str()); } while (1)
;
639 }
640
641 // Try to create the address object. It also validates that
642 // the address syntax is ok.
643 isc::asiolink::IOAddress addr(subnet_txt.substr(0, pos));
644
645 // Now parse out the prefix length.
646 unsigned int len;
647 try {
648 len = boost::lexical_cast<unsigned int>(subnet_txt.substr(pos + 1));
649 } catch (const boost::bad_lexical_cast&) {
650 ConstElementPtr elem = params->get("subnet");
651 isc_throw(DhcpConfigError, "prefix length: '" <<do { std::ostringstream oss__; oss__ << "prefix length: '"
<< subnet_txt.substr(pos+1) << "' is not an integer ("
<< elem->getPosition() << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 653, oss__.str().c_str()); } while
(1)
652 subnet_txt.substr(pos+1) << "' is not an integer ("do { std::ostringstream oss__; oss__ << "prefix length: '"
<< subnet_txt.substr(pos+1) << "' is not an integer ("
<< elem->getPosition() << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 653, oss__.str().c_str()); } while
(1)
653 << elem->getPosition() << ")")do { std::ostringstream oss__; oss__ << "prefix length: '"
<< subnet_txt.substr(pos+1) << "' is not an integer ("
<< elem->getPosition() << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 653, oss__.str().c_str()); } while
(1)
;
654 }
655
656 // Sanity check the prefix length
657 if ((addr.isV6() && len > 128) ||
658 (addr.isV4() && len > 32)) {
659 ConstElementPtr elem = params->get("subnet");
660 isc_throw(BadValue,do { std::ostringstream oss__; oss__ << "Invalid prefix length specified for subnet: "
<< len << " (" << elem->getPosition() <<
")"; throw BadValue("parsers/dhcp_parsers.cc", 662, oss__.str
().c_str()); } while (1)
661 "Invalid prefix length specified for subnet: " << lendo { std::ostringstream oss__; oss__ << "Invalid prefix length specified for subnet: "
<< len << " (" << elem->getPosition() <<
")"; throw BadValue("parsers/dhcp_parsers.cc", 662, oss__.str
().c_str()); } while (1)
662 << " (" << elem->getPosition() << ")")do { std::ostringstream oss__; oss__ << "Invalid prefix length specified for subnet: "
<< len << " (" << elem->getPosition() <<
")"; throw BadValue("parsers/dhcp_parsers.cc", 662, oss__.str
().c_str()); } while (1)
;
663 }
664
665 // Call the subclass's method to instantiate the subnet
666 initSubnet(params, addr, len);
667
668 // Add pools to it.
669 for (auto const& pool : *pools_) {
670 try {
671 subnet_->addPool(pool);
672 } catch (const BadValue& ex) {
673 // addPool() can throw BadValue if the pool is overlapping or
674 // is out of bounds for the subnet.
675 isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << ex.what() <<
" (" << params->getPosition() << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 676, oss__.str().c_str()); } while
(1)
676 ex.what() << " (" << params->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() <<
" (" << params->getPosition() << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 676, oss__.str().c_str()); } while
(1)
;
677 }
678 }
679 // If there's user-context specified, store it.
680 ConstElementPtr user_context = params->get("user-context");
681 if (user_context) {
682 // The grammar accepts only maps but still check it.
683 if (user_context->getType() != Element::map) {
684 isc_throw(isc::dhcp::DhcpConfigError, "User context has to be a map ("do { std::ostringstream oss__; oss__ << "User context has to be a map ("
<< user_context->getPosition() << ")"; throw isc
::dhcp::DhcpConfigError("parsers/dhcp_parsers.cc", 685, oss__
.str().c_str()); } while (1)
685 << user_context->getPosition() << ")")do { std::ostringstream oss__; oss__ << "User context has to be a map ("
<< user_context->getPosition() << ")"; throw isc
::dhcp::DhcpConfigError("parsers/dhcp_parsers.cc", 685, oss__
.str().c_str()); } while (1)
;
686 }
687 subnet_->setContext(user_context);
688 }
689
690 // In order to take advantage of the dynamic inheritance of global
691 // parameters to a subnet we need to set a callback function for each
692 // subnet to allow for fetching global parameters.
693 subnet_->setFetchGlobalsFn([]() -> ConstCfgGlobalsPtr {
694 return (CfgMgr::instance().getCurrentCfg()->getConfiguredGlobals());
695 });
696}
697
698boost::shared_ptr<OptionDataListParser>
699SubnetConfigParser::createOptionDataListParser() const {
700 return (boost::make_shared<OptionDataListParser>(address_family_));
701}
702
703//****************************** Subnet4ConfigParser *************************
704
705Subnet4ConfigParser::Subnet4ConfigParser(bool check_iface)
706 : SubnetConfigParser(AF_INET2, check_iface) {
707}
708
709Subnet4Ptr
710Subnet4ConfigParser::parse(ConstElementPtr subnet, bool encapsulate_options) {
711 // Check parameters.
712 checkKeywords(SimpleParser4::SUBNET4_PARAMETERS, subnet);
713
714 /// Parse Pools first.
715 ConstElementPtr pools = subnet->get("pools");
716 if (pools) {
717 auto const& parser = createPoolsListParser();
718 parser->parse(pools_, pools, encapsulate_options);
719 }
720
721 SubnetPtr generic = SubnetConfigParser::parse(subnet, encapsulate_options);
722
723 if (!generic) {
724 // Sanity check: not supposed to fail.
725 isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "Failed to create an IPv4 subnet ("
<< subnet->getPosition() << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 727, oss__.str().c_str()); } while
(1)
726 "Failed to create an IPv4 subnet (" <<do { std::ostringstream oss__; oss__ << "Failed to create an IPv4 subnet ("
<< subnet->getPosition() << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 727, oss__.str().c_str()); } while
(1)
727 subnet->getPosition() << ")")do { std::ostringstream oss__; oss__ << "Failed to create an IPv4 subnet ("
<< subnet->getPosition() << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 727, oss__.str().c_str()); } while
(1)
;
728 }
729
730 Subnet4Ptr sn4ptr = boost::dynamic_pointer_cast<Subnet4>(subnet_);
731 if (!sn4ptr) {
732 // If we hit this, it is a programming error.
733 isc_throw(Unexpected,do { std::ostringstream oss__; oss__ << "Invalid Subnet4 cast in Subnet4ConfigParser::parse"
; throw Unexpected("parsers/dhcp_parsers.cc", 734, oss__.str(
).c_str()); } while (1)
734 "Invalid Subnet4 cast in Subnet4ConfigParser::parse")do { std::ostringstream oss__; oss__ << "Invalid Subnet4 cast in Subnet4ConfigParser::parse"
; throw Unexpected("parsers/dhcp_parsers.cc", 734, oss__.str(
).c_str()); } while (1)
;
735 }
736
737 // Set relay information if it was parsed
738 if (relay_info_) {
739 sn4ptr->setRelayInfo(*relay_info_);
740 }
741
742 // Parse Host Reservations for this subnet if any.
743 ConstElementPtr reservations = subnet->get("reservations");
744 if (reservations) {
745 HostCollection hosts;
746 HostReservationsListParser<HostReservationParser4> parser;
747 parser.parse(subnet_->getID(), reservations, hosts);
748 for (auto const& h : hosts) {
749 validateResv(sn4ptr, h);
750 CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(h);
751 }
752 }
753
754 // Parse allocator specification.
755 auto network4 = boost::dynamic_pointer_cast<Network>(sn4ptr);
756 parseAllocatorParams(subnet, network4);
757
758 // Instantiate the allocator.
759 sn4ptr->createAllocators();
760
761 return (sn4ptr);
762}
763
764void
765Subnet4ConfigParser::initSubnet(data::ConstElementPtr params,
766 asiolink::IOAddress addr, uint8_t len) {
767 // Subnet ID is required and must be in 1..SUBNET_ID_MAX.
768 int64_t subnet_id_max = static_cast<int64_t>(SUBNET_ID_MAX);
769 SubnetID subnet_id = static_cast<SubnetID>(getInteger(params, "id", 1,
770 subnet_id_max));
771
772 auto subnet4 = Subnet4::create(addr, len, Triplet<uint32_t>(),
773 Triplet<uint32_t>(), Triplet<uint32_t>(),
774 subnet_id);
775 subnet_ = subnet4;
776
777 ElementPtr mutable_params;
778 mutable_params = boost::const_pointer_cast<Element>(params);
779
780 // Parse parameters common to all Network derivations.
781 NetworkPtr network = boost::dynamic_pointer_cast<Network>(subnet4);
782 parseCommon(mutable_params, network);
783
784 std::ostringstream output;
785 output << addr << "/" << static_cast<int>(len) << " with params: ";
786
787 bool has_renew = !subnet4->getT1().unspecified();
788 bool has_rebind = !subnet4->getT2().unspecified();
789 int64_t renew = -1;
790 int64_t rebind = -1;
791
792 // t1 and t2 are optional may be not specified.
793 if (has_renew) {
794 renew = subnet4->getT1().get();
795 output << "t1=" << renew << ", ";
796 }
797 if (has_rebind) {
798 rebind = subnet4->getT2().get();
799 output << "t2=" << rebind << ", ";
800 }
801
802 if (!subnet4->getValid().unspecified()) {
803 output << "valid-lifetime=" << subnet4->getValid().get();
804 }
805
806 LOG_INFO(dhcpsrv_logger, DHCPSRV_CFGMGR_NEW_SUBNET4)if (!(dhcpsrv_logger).isInfoEnabled()) { } else (dhcpsrv_logger
).info((DHCPSRV_CFGMGR_NEW_SUBNET4))
.arg(output.str());
807
808 // Set the match-client-id value for the subnet.
809 if (params->contains("match-client-id")) {
810 bool match_client_id = getBoolean(params, "match-client-id");
811 subnet4->setMatchClientId(match_client_id);
812 }
813
814 // Set the authoritative value for the subnet.
815 if (params->contains("authoritative")) {
816 bool authoritative = getBoolean(params, "authoritative");
817 subnet4->setAuthoritative(authoritative);
818 }
819
820 // Set next-server. The default value is 0.0.0.0. Nevertheless, the
821 // user could have messed that up by specifying incorrect value.
822 // To avoid using 0.0.0.0, user can specify "".
823 if (params->contains("next-server")) {
824 string next_server;
825 try {
826 next_server = getString(params, "next-server");
827 if (!next_server.empty()) {
828 subnet4->setSiaddr(IOAddress(next_server));
829 }
830 } catch (...) {
831 ConstElementPtr next = params->get("next-server");
832 string pos;
833 if (next) {
834 pos = next->getPosition().str();
835 } else {
836 pos = params->getPosition().str();
837 }
838 isc_throw(DhcpConfigError, "invalid parameter next-server : "do { std::ostringstream oss__; oss__ << "invalid parameter next-server : "
<< next_server << "(" << pos << ")";
throw DhcpConfigError("parsers/dhcp_parsers.cc", 839, oss__.
str().c_str()); } while (1)
839 << next_server << "(" << pos << ")")do { std::ostringstream oss__; oss__ << "invalid parameter next-server : "
<< next_server << "(" << pos << ")";
throw DhcpConfigError("parsers/dhcp_parsers.cc", 839, oss__.
str().c_str()); } while (1)
;
840 }
841 }
842
843 // Set server-hostname.
844 if (params->contains("server-hostname")) {
845 std::string sname = getString(params, "server-hostname");
846 if (!sname.empty()) {
847 if (sname.length() >= Pkt4::MAX_SNAME_LEN) {
848 ConstElementPtr error = params->get("server-hostname");
849 isc_throw(DhcpConfigError, "server-hostname must be at most "do { std::ostringstream oss__; oss__ << "server-hostname must be at most "
<< Pkt4::MAX_SNAME_LEN - 1 << " bytes long, it is "
<< sname.length() << " (" << error->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 852, oss__.str().c_str()); } while (1)
850 << Pkt4::MAX_SNAME_LEN - 1 << " bytes long, it is "do { std::ostringstream oss__; oss__ << "server-hostname must be at most "
<< Pkt4::MAX_SNAME_LEN - 1 << " bytes long, it is "
<< sname.length() << " (" << error->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 852, oss__.str().c_str()); } while (1)
851 << sname.length() << " ("do { std::ostringstream oss__; oss__ << "server-hostname must be at most "
<< Pkt4::MAX_SNAME_LEN - 1 << " bytes long, it is "
<< sname.length() << " (" << error->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 852, oss__.str().c_str()); } while (1)
852 << error->getPosition() << ")")do { std::ostringstream oss__; oss__ << "server-hostname must be at most "
<< Pkt4::MAX_SNAME_LEN - 1 << " bytes long, it is "
<< sname.length() << " (" << error->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 852, oss__.str().c_str()); } while (1)
;
853 }
854 subnet4->setSname(sname);
855 }
856 }
857
858 // Set boot-file-name.
859 if (params->contains("boot-file-name")) {
860 std::string filename =getString(params, "boot-file-name");
861 if (!filename.empty()) {
862 if (filename.length() > Pkt4::MAX_FILE_LEN) {
863 ConstElementPtr error = params->get("boot-file-name");
864 isc_throw(DhcpConfigError, "boot-file-name must be at most "do { std::ostringstream oss__; oss__ << "boot-file-name must be at most "
<< Pkt4::MAX_FILE_LEN - 1 << " bytes long, it is "
<< filename.length() << " (" << error->
getPosition() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 867, oss__.str().c_str()); } while (1)
865 << Pkt4::MAX_FILE_LEN - 1 << " bytes long, it is "do { std::ostringstream oss__; oss__ << "boot-file-name must be at most "
<< Pkt4::MAX_FILE_LEN - 1 << " bytes long, it is "
<< filename.length() << " (" << error->
getPosition() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 867, oss__.str().c_str()); } while (1)
866 << filename.length() << " ("do { std::ostringstream oss__; oss__ << "boot-file-name must be at most "
<< Pkt4::MAX_FILE_LEN - 1 << " bytes long, it is "
<< filename.length() << " (" << error->
getPosition() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 867, oss__.str().c_str()); } while (1)
867 << error->getPosition() << ")")do { std::ostringstream oss__; oss__ << "boot-file-name must be at most "
<< Pkt4::MAX_FILE_LEN - 1 << " bytes long, it is "
<< filename.length() << " (" << error->
getPosition() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 867, oss__.str().c_str()); } while (1)
;
868 }
869 subnet4->setFilename(filename);
870 }
871 }
872
873 // Get interface name. If it is defined, then the subnet is available
874 // directly over specified network interface.
875 if (params->contains("interface")) {
876 std::string iface = getString(params, "interface");
877 if (!iface.empty()) {
878 if (check_iface_ && !IfaceMgr::instance().getIface(iface)) {
879 ConstElementPtr error = params->get("interface");
880 isc_throw(DhcpConfigError, "Specified network interface name " << ifacedo { std::ostringstream oss__; oss__ << "Specified network interface name "
<< iface << " for subnet " << subnet4->
toText() << " is not present in the system (" << error
->getPosition() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 883, oss__.str().c_str()); } while (1)
881 << " for subnet " << subnet4->toText()do { std::ostringstream oss__; oss__ << "Specified network interface name "
<< iface << " for subnet " << subnet4->
toText() << " is not present in the system (" << error
->getPosition() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 883, oss__.str().c_str()); } while (1)
882 << " is not present in the system ("do { std::ostringstream oss__; oss__ << "Specified network interface name "
<< iface << " for subnet " << subnet4->
toText() << " is not present in the system (" << error
->getPosition() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 883, oss__.str().c_str()); } while (1)
883 << error->getPosition() << ")")do { std::ostringstream oss__; oss__ << "Specified network interface name "
<< iface << " for subnet " << subnet4->
toText() << " is not present in the system (" << error
->getPosition() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 883, oss__.str().c_str()); } while (1)
;
884 }
885
886 subnet4->setIface(iface);
887 }
888 }
889
890 // Try setting up client class.
891 if (params->contains("client-class")) {
892 string client_class = getString(params, "client-class");
893 if (!client_class.empty()) {
894 subnet4->allowClientClass(client_class);
895 }
896 }
897
898 // Setup client class list.
899 getClientClassesElem(params, std::bind(&Network::allowClientClass,
900 subnet4, ph::_1));
901
902 // Setup additional class list.
903 getAdditionalClassesElem(params, std::bind(&Network::addAdditionalClass,
904 subnet4, ph::_1));
905
906 // 4o6 specific parameter: 4o6-interface.
907 if (params->contains("4o6-interface")) {
908 string iface4o6 = getString(params, "4o6-interface");
909 if (!iface4o6.empty()) {
910 subnet4->get4o6().setIface4o6(iface4o6);
911 subnet4->get4o6().enabled(true);
912 }
913 }
914
915 // 4o6 specific parameter: 4o6-subnet.
916 if (params->contains("4o6-subnet")) {
917 string subnet4o6 = getString(params, "4o6-subnet");
918 if (!subnet4o6.empty()) {
919 size_t slash = subnet4o6.find("/");
920 if (slash == std::string::npos) {
921 isc_throw(DhcpConfigError, "Missing / in the 4o6-subnet parameter:"do { std::ostringstream oss__; oss__ << "Missing / in the 4o6-subnet parameter:"
<< subnet4o6 << ", expected format: prefix6/length"
; throw DhcpConfigError("parsers/dhcp_parsers.cc", 922, oss__
.str().c_str()); } while (1)
922 << subnet4o6 << ", expected format: prefix6/length")do { std::ostringstream oss__; oss__ << "Missing / in the 4o6-subnet parameter:"
<< subnet4o6 << ", expected format: prefix6/length"
; throw DhcpConfigError("parsers/dhcp_parsers.cc", 922, oss__
.str().c_str()); } while (1)
;
923 }
924 string prefix = subnet4o6.substr(0, slash);
925 string lenstr = subnet4o6.substr(slash + 1);
926
927 len = 128;
Value stored to 'len' is never read
928 try {
929 len = boost::lexical_cast<unsigned int>(lenstr.c_str());
930 } catch (const boost::bad_lexical_cast &) {
931 isc_throw(DhcpConfigError, "Invalid prefix length specified in "do { std::ostringstream oss__; oss__ << "Invalid prefix length specified in "
"4o6-subnet parameter: " << subnet4o6 << ", expected 0..128 value"
; throw DhcpConfigError("parsers/dhcp_parsers.cc", 932, oss__
.str().c_str()); } while (1)
932 "4o6-subnet parameter: " << subnet4o6 << ", expected 0..128 value")do { std::ostringstream oss__; oss__ << "Invalid prefix length specified in "
"4o6-subnet parameter: " << subnet4o6 << ", expected 0..128 value"
; throw DhcpConfigError("parsers/dhcp_parsers.cc", 932, oss__
.str().c_str()); } while (1)
;
933 }
934 subnet4->get4o6().setSubnet4o6(IOAddress(prefix), len);
935 subnet4->get4o6().enabled(true);
936 }
937 }
938
939 // Try 4o6 specific parameter: 4o6-interface-id
940 if (params->contains("4o6-interface-id")) {
941 std::string ifaceid = getString(params, "4o6-interface-id");
942 if (!ifaceid.empty()) {
943 OptionBuffer tmp(ifaceid.begin(), ifaceid.end());
944 OptionPtr opt(new Option(Option::V6, D6O_INTERFACE_ID, tmp));
945 subnet4->get4o6().setInterfaceId(opt);
946 subnet4->get4o6().enabled(true);
947 }
948 }
949
950 /// client-class processing is now generic and handled in the common
951 /// code (see isc::data::SubnetConfigParser::createSubnet)
952
953 // Here globally defined options were merged to the subnet specific
954 // options but this is no longer the case (they have a different
955 // and not consecutive priority).
956
957 // Parse t1-percent and t2-percent
958 parseTeePercents(params, network);
959
960 // Parse DDNS parameters
961 parseDdnsParams(params, network);
962
963 // Parse lease cache parameters
964 parseCacheParams(params, network);
965
966 // Set the offer_lft value for the subnet.
967 if (params->contains("offer-lifetime")) {
968 uint32_t offer_lft = getInteger(params, "offer-lifetime");
969 subnet4->setOfferLft(offer_lft);
970 }
971
972 // Parse offer-lifetime parameter.
973 Network4Ptr network4 = boost::dynamic_pointer_cast<Network4>(subnet4);
974 parseOfferLft(params, network4);
975
976}
977
978void
979Subnet4ConfigParser::validateResv(const Subnet4Ptr& subnet, ConstHostPtr host) {
980 const IOAddress& address = host->getIPv4Reservation();
981 if (!address.isV4Zero() && !subnet->inRange(address)) {
982 isc_throw(DhcpConfigError, "specified reservation '" << addressdo { std::ostringstream oss__; oss__ << "specified reservation '"
<< address << "' is not within the IPv4 subnet '"
<< subnet->toText() << "'"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 984, oss__.str().c_str()); } while
(1)
983 << "' is not within the IPv4 subnet '"do { std::ostringstream oss__; oss__ << "specified reservation '"
<< address << "' is not within the IPv4 subnet '"
<< subnet->toText() << "'"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 984, oss__.str().c_str()); } while
(1)
984 << subnet->toText() << "'")do { std::ostringstream oss__; oss__ << "specified reservation '"
<< address << "' is not within the IPv4 subnet '"
<< subnet->toText() << "'"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 984, oss__.str().c_str()); } while
(1)
;
985 }
986}
987
988boost::shared_ptr<PoolsListParser>
989Subnet4ConfigParser::createPoolsListParser() const {
990 return (boost::make_shared<Pools4ListParser>());
991}
992
993//**************************** Subnets4ListConfigParser **********************
994
995Subnets4ListConfigParser::Subnets4ListConfigParser(bool check_iface)
996 : check_iface_(check_iface) {
997}
998
999size_t
1000Subnets4ListConfigParser::parse(SrvConfigPtr cfg,
1001 ConstElementPtr subnets_list,
1002 bool encapsulate_options) {
1003 size_t cnt = 0;
1004 for (auto const& subnet_json : subnets_list->listValue()) {
1005
1006 auto const& parser = createSubnetConfigParser();
1007 Subnet4Ptr subnet = parser->parse(subnet_json, encapsulate_options);
1008 if (subnet) {
1009
1010 // Adding a subnet to the Configuration Manager may fail if the
1011 // subnet id is invalid (duplicate). Thus, we catch exceptions
1012 // here to append a position in the configuration string.
1013 try {
1014 cfg->getCfgSubnets4()->add(subnet);
1015 cnt++;
1016 } catch (const std::exception& ex) {
1017 isc_throw(DhcpConfigError, ex.what() << " ("do { std::ostringstream oss__; oss__ << ex.what() <<
" (" << subnet_json->getPosition() << ")"; throw
DhcpConfigError("parsers/dhcp_parsers.cc", 1018, oss__.str()
.c_str()); } while (1)
1018 << subnet_json->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() <<
" (" << subnet_json->getPosition() << ")"; throw
DhcpConfigError("parsers/dhcp_parsers.cc", 1018, oss__.str()
.c_str()); } while (1)
;
1019 }
1020 }
1021 }
1022 return (cnt);
1023}
1024
1025size_t
1026Subnets4ListConfigParser::parse(Subnet4Collection& subnets,
1027 data::ConstElementPtr subnets_list,
1028 bool encapsulate_options) {
1029 size_t cnt = 0;
1030 for (auto const& subnet_json : subnets_list->listValue()) {
1031
1032 auto const& parser = createSubnetConfigParser();
1033 Subnet4Ptr subnet = parser->parse(subnet_json, encapsulate_options);
1034 if (subnet) {
1035 try {
1036 auto ret = subnets.insert(subnet);
1037 if (!ret.second) {
1038 isc_throw(Unexpected,do { std::ostringstream oss__; oss__ << "can't store subnet because of conflict"
; throw Unexpected("parsers/dhcp_parsers.cc", 1039, oss__.str
().c_str()); } while (1)
1039 "can't store subnet because of conflict")do { std::ostringstream oss__; oss__ << "can't store subnet because of conflict"
; throw Unexpected("parsers/dhcp_parsers.cc", 1039, oss__.str
().c_str()); } while (1)
;
1040 }
1041 ++cnt;
1042 } catch (const std::exception& ex) {
1043 isc_throw(DhcpConfigError, ex.what() << " ("do { std::ostringstream oss__; oss__ << ex.what() <<
" (" << subnet_json->getPosition() << ")"; throw
DhcpConfigError("parsers/dhcp_parsers.cc", 1044, oss__.str()
.c_str()); } while (1)
1044 << subnet_json->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() <<
" (" << subnet_json->getPosition() << ")"; throw
DhcpConfigError("parsers/dhcp_parsers.cc", 1044, oss__.str()
.c_str()); } while (1)
;
1045 }
1046 }
1047 }
1048 return (cnt);
1049}
1050
1051boost::shared_ptr<Subnet4ConfigParser>
1052Subnets4ListConfigParser::createSubnetConfigParser() const {
1053 return (boost::make_shared<Subnet4ConfigParser>(check_iface_));
1054}
1055
1056//**************************** Pool6Parser *********************************
1057
1058PoolPtr
1059Pool6Parser::poolMaker(IOAddress &addr, uint32_t len, int32_t ptype)
1060{
1061 return (PoolPtr(new Pool6(static_cast<isc::dhcp::Lease::Type>
1062 (ptype), addr, len)));
1063}
1064
1065PoolPtr
1066Pool6Parser::poolMaker(IOAddress &min, IOAddress &max, int32_t ptype)
1067{
1068 return (PoolPtr(new Pool6(static_cast<isc::dhcp::Lease::Type>
1069 (ptype), min, max)));
1070}
1071
1072
1073//**************************** Pool6ListParser ***************************
1074
1075void
1076Pools6ListParser::parse(PoolStoragePtr pools, ConstElementPtr pools_list,
1077 bool encapsulate_options) {
1078 for (auto const& pool : pools_list->listValue()) {
1079 auto const& parser = createPoolConfigParser();
1080 parser->parse(pools, pool, AF_INET610, encapsulate_options);
1081 }
1082}
1083
1084boost::shared_ptr<PoolParser>
1085Pools6ListParser::createPoolConfigParser() const {
1086 return (boost::make_shared<Pool6Parser>());
1087}
1088
1089//**************************** PdPoolParser ******************************
1090
1091PdPoolParser::PdPoolParser() {
1092}
1093
1094void
1095PdPoolParser::parse(PoolStoragePtr pools, ConstElementPtr pd_pool,
1096 bool encapsulate_options) {
1097 checkKeywords(SimpleParser6::PD_POOL6_PARAMETERS, pd_pool);
1098
1099 std::string addr_str = getString(pd_pool, "prefix");
1100
1101 uint8_t prefix_len = getUint8(pd_pool, "prefix-len");
1102
1103 uint8_t delegated_len = getUint8(pd_pool, "delegated-len");
1104
1105 std::string excluded_prefix_str = "::";
1106 if (pd_pool->contains("excluded-prefix")) {
1107 excluded_prefix_str = getString(pd_pool, "excluded-prefix");
1108 }
1109
1110 uint8_t excluded_prefix_len = 0;
1111 if (pd_pool->contains("excluded-prefix-len")) {
1112 excluded_prefix_len = getUint8(pd_pool, "excluded-prefix-len");
1113 }
1114
1115 ConstElementPtr user_context = pd_pool->get("user-context");
1116 if (user_context) {
1117 user_context_ = user_context;
1118 }
1119
1120 ConstElementPtr client_class = pd_pool->get("client-class");
1121 if (client_class) {
1122 client_class_ = client_class;
1123 }
1124
1125 // Check the pool parameters. It will throw an exception if any
1126 // of the required parameters are invalid.
1127 try {
1128 // Attempt to construct the local pool.
1129 pool_.reset(new Pool6(IOAddress(addr_str),
1130 prefix_len,
1131 delegated_len,
1132 IOAddress(excluded_prefix_str),
1133 excluded_prefix_len));
1134 } catch (const std::exception& ex) {
1135 // Some parameters don't exist or are invalid. Since we are not
1136 // aware whether they don't exist or are invalid, let's append
1137 // the position of the pool map element.
1138 isc_throw(isc::dhcp::DhcpConfigError, ex.what()do { std::ostringstream oss__; oss__ << ex.what() <<
" (" << pd_pool->getPosition() << ")"; throw isc
::dhcp::DhcpConfigError("parsers/dhcp_parsers.cc", 1139, oss__
.str().c_str()); } while (1)
1139 << " (" << pd_pool->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() <<
" (" << pd_pool->getPosition() << ")"; throw isc
::dhcp::DhcpConfigError("parsers/dhcp_parsers.cc", 1139, oss__
.str().c_str()); } while (1)
;
1140 }
1141
1142 // If there is a pool-id, store it.
1143 ConstElementPtr pool_id = pd_pool->get("pool-id");
1144 if (pool_id) {
1145 if (pool_id->intValue() <= 0) {
1146 isc_throw(BadValue, "pool-id " << pool_id->intValue() << " is not"do { std::ostringstream oss__; oss__ << "pool-id " <<
pool_id->intValue() << " is not" << " a positive integer greater than 0"
; throw BadValue("parsers/dhcp_parsers.cc", 1147, oss__.str()
.c_str()); } while (1)
1147 << " a positive integer greater than 0")do { std::ostringstream oss__; oss__ << "pool-id " <<
pool_id->intValue() << " is not" << " a positive integer greater than 0"
; throw BadValue("parsers/dhcp_parsers.cc", 1147, oss__.str()
.c_str()); } while (1)
;
1148 } else if (pool_id->intValue() > numeric_limits<uint32_t>::max()) {
1149 isc_throw(BadValue, "pool-id " << pool_id->intValue() << " is not"do { std::ostringstream oss__; oss__ << "pool-id " <<
pool_id->intValue() << " is not" << " a 32 bit unsigned integer"
; throw BadValue("parsers/dhcp_parsers.cc", 1150, oss__.str()
.c_str()); } while (1)
1150 << " a 32 bit unsigned integer")do { std::ostringstream oss__; oss__ << "pool-id " <<
pool_id->intValue() << " is not" << " a 32 bit unsigned integer"
; throw BadValue("parsers/dhcp_parsers.cc", 1150, oss__.str()
.c_str()); } while (1)
;
1151 }
1152
1153 pool_->setID(pool_id->intValue());
1154 }
1155
1156 // We create subnet first and then parse the options straight into the subnet's
1157 // CfgOption structure. Previously, we first parsed the options and then copied
1158 // them into the CfgOption after creating the subnet but it had two issues. First,
1159 // it cost performance. Second, copying options reset the isEncapsulated() flag.
1160 // If the options have been encapsulated we want to preserve the flag to ensure
1161 // they are not encapsulated several times.
1162 ConstElementPtr option_data = pd_pool->get("option-data");
1163 if (option_data) {
1164 auto opts_parser = createOptionDataListParser();
1165 opts_parser->parse(pool_->getCfgOption(), option_data, encapsulate_options);
1166 }
1167
1168 if (user_context_) {
1169 pool_->setContext(user_context_);
1170 }
1171
1172 if (client_class_) {
1173 string cclass = client_class_->stringValue();
1174 if (!cclass.empty()) {
1175 pool_->allowClientClass(cclass);
1176 }
1177 }
1178
1179 // Setup client class list.
1180 BaseNetworkParser::getClientClassesElem(pd_pool,
1181 std::bind(&Pool::allowClientClass,
1182 pool_, ph::_1));
1183
1184 // Setup additional class list.
1185 BaseNetworkParser::getAdditionalClassesElem(pd_pool,
1186 std::bind(&Pool::addAdditionalClass,
1187 pool_, ph::_1));
1188
1189 // Add the local pool to the external storage ptr.
1190 pools->push_back(pool_);
1191}
1192
1193boost::shared_ptr<OptionDataListParser>
1194PdPoolParser::createOptionDataListParser() const {
1195 return (boost::make_shared<OptionDataListParser>(AF_INET610));
1196}
1197
1198//**************************** PdPoolsListParser ************************
1199
1200void
1201PdPoolsListParser::parse(PoolStoragePtr pools, ConstElementPtr pd_pool_list) {
1202 // Loop through the list of pd pools.
1203 for (auto const& pd_pool : pd_pool_list->listValue()) {
1204 auto const& parser = createPdPoolConfigParser();
1205 parser->parse(pools, pd_pool);
1206 }
1207}
1208
1209boost::shared_ptr<PdPoolParser>
1210PdPoolsListParser::createPdPoolConfigParser() const {
1211 return (boost::make_shared<PdPoolParser>());
1212}
1213
1214//**************************** Subnet6ConfigParser ***********************
1215
1216Subnet6ConfigParser::Subnet6ConfigParser(bool check_iface)
1217 : SubnetConfigParser(AF_INET610, check_iface) {
1218}
1219
1220Subnet6Ptr
1221Subnet6ConfigParser::parse(ConstElementPtr subnet, bool encapsulate_options) {
1222 // Check parameters.
1223 checkKeywords(SimpleParser6::SUBNET6_PARAMETERS, subnet);
1224
1225 /// Parse all pools first.
1226 ConstElementPtr pools = subnet->get("pools");
1227 if (pools) {
1228 auto const& parser = createPoolsListParser();
1229 parser->parse(pools_, pools, encapsulate_options);
1230 }
1231 ConstElementPtr pd_pools = subnet->get("pd-pools");
1232 if (pd_pools) {
1233 auto const& parser = createPdPoolsListParser();
1234 parser->parse(pools_, pd_pools);
1235 }
1236
1237 SubnetPtr generic = SubnetConfigParser::parse(subnet, encapsulate_options);
1238
1239 if (!generic) {
1240 // Sanity check: not supposed to fail.
1241 isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "Failed to create an IPv6 subnet ("
<< subnet->getPosition() << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 1243, oss__.str().c_str()); } while
(1)
1242 "Failed to create an IPv6 subnet (" <<do { std::ostringstream oss__; oss__ << "Failed to create an IPv6 subnet ("
<< subnet->getPosition() << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 1243, oss__.str().c_str()); } while
(1)
1243 subnet->getPosition() << ")")do { std::ostringstream oss__; oss__ << "Failed to create an IPv6 subnet ("
<< subnet->getPosition() << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 1243, oss__.str().c_str()); } while
(1)
;
1244 }
1245
1246 Subnet6Ptr sn6ptr = boost::dynamic_pointer_cast<Subnet6>(subnet_);
1247 if (!sn6ptr) {
1248 // If we hit this, it is a programming error.
1249 isc_throw(Unexpected,do { std::ostringstream oss__; oss__ << "Invalid Subnet6 cast in Subnet6ConfigParser::parse"
; throw Unexpected("parsers/dhcp_parsers.cc", 1250, oss__.str
().c_str()); } while (1)
1250 "Invalid Subnet6 cast in Subnet6ConfigParser::parse")do { std::ostringstream oss__; oss__ << "Invalid Subnet6 cast in Subnet6ConfigParser::parse"
; throw Unexpected("parsers/dhcp_parsers.cc", 1250, oss__.str
().c_str()); } while (1)
;
1251 }
1252
1253 // Set relay information if it was provided
1254 if (relay_info_) {
1255 sn6ptr->setRelayInfo(*relay_info_);
1256 }
1257
1258 // Parse Host Reservations for this subnet if any.
1259 ConstElementPtr reservations = subnet->get("reservations");
1260 if (reservations) {
1261 HostCollection hosts;
1262 HostReservationsListParser<HostReservationParser6> parser;
1263 parser.parse(subnet_->getID(), reservations, hosts);
1264 for (auto const& h : hosts) {
1265 validateResvs(sn6ptr, h);
1266 CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(h);
1267 }
1268 }
1269
1270 // Parse allocator specification.
1271 auto network = boost::dynamic_pointer_cast<Network>(sn6ptr);
1272 parseAllocatorParams(subnet, network);
1273
1274 // Parse pd-allocator specification.
1275 auto network6 = boost::dynamic_pointer_cast<Network6>(sn6ptr);
1276 parsePdAllocatorParams(subnet, network6);
1277
1278 // Instantiate the allocators.
1279 sn6ptr->createAllocators();
1280
1281 return (sn6ptr);
1282}
1283
1284// Unused?
1285void
1286Subnet6ConfigParser::duplicateOptionWarning(uint32_t code,
1287 asiolink::IOAddress& addr) {
1288 LOG_WARN(dhcpsrv_logger, DHCPSRV_CFGMGR_OPTION_DUPLICATE)if (!(dhcpsrv_logger).isWarnEnabled()) { } else (dhcpsrv_logger
).warn((DHCPSRV_CFGMGR_OPTION_DUPLICATE))
1289 .arg(code).arg(addr.toText());
1290}
1291
1292void
1293Subnet6ConfigParser::initSubnet(data::ConstElementPtr params,
1294 asiolink::IOAddress addr, uint8_t len) {
1295 // Subnet ID is required and must be in 1..SUBNET_ID_MAX.
1296 int64_t subnet_id_max = static_cast<int64_t>(SUBNET_ID_MAX);
1297 SubnetID subnet_id = static_cast<SubnetID>(getInteger(params, "id", 1,
1298 subnet_id_max));
1299
1300 // We want to log whether rapid-commit is enabled, so we get this
1301 // before the actual subnet creation.
1302 Optional<bool> rapid_commit;
1303 if (params->contains("rapid-commit")) {
1304 rapid_commit = getBoolean(params, "rapid-commit");
1305 }
1306
1307 // Parse preferred lifetime as it is not parsed by the common function.
1308 Triplet<uint32_t> pref = parseIntTriplet(params, "preferred-lifetime");
1309
1310 // Create a new subnet.
1311 auto subnet6 = Subnet6::create(addr, len, Triplet<uint32_t>(),
1312 Triplet<uint32_t>(),
1313 pref,
1314 Triplet<uint32_t>(),
1315 subnet_id);
1316 subnet_ = subnet6;
1317
1318 ElementPtr mutable_params;
1319 mutable_params = boost::const_pointer_cast<Element>(params);
1320
1321 // Parse parameters common to all Network derivations.
1322 NetworkPtr network = boost::dynamic_pointer_cast<Network>(subnet_);
1323 parseCommon(mutable_params, network);
1324
1325 // Enable or disable Rapid Commit option support for the subnet.
1326 if (!rapid_commit.unspecified()) {
1327 subnet6->setRapidCommit(rapid_commit);
1328 }
1329
1330 std::ostringstream output;
1331 output << addr << "/" << static_cast<int>(len) << " with params: ";
1332 // t1 and t2 are optional may be not specified.
1333
1334 bool has_renew = !subnet6->getT1().unspecified();
1335 bool has_rebind = !subnet6->getT2().unspecified();
1336 int64_t renew = -1;
1337 int64_t rebind = -1;
1338
1339 if (has_renew) {
1340 renew = subnet6->getT1().get();
1341 output << "t1=" << renew << ", ";
1342 }
1343 if (has_rebind) {
1344 rebind = subnet6->getT2().get();
1345 output << "t2=" << rebind << ", ";
1346 }
1347
1348 if (!subnet6->getPreferred().unspecified()) {
1349 output << "preferred-lifetime=" << subnet6->getPreferred().get() << ", ";
1350 }
1351 if (!subnet6->getValid().unspecified()) {
1352 output << "valid-lifetime=" << subnet6->getValid().get();
1353 }
1354 if (!subnet6->getRapidCommit().unspecified()) {
1355 output << ", rapid-commit is "
1356 << boolalpha << subnet6->getRapidCommit().get();
1357 }
1358
1359 LOG_INFO(dhcpsrv_logger, DHCPSRV_CFGMGR_NEW_SUBNET6)if (!(dhcpsrv_logger).isInfoEnabled()) { } else (dhcpsrv_logger
).info((DHCPSRV_CFGMGR_NEW_SUBNET6))
.arg(output.str());
1360
1361 // Get interface-id option content. For now we support string
1362 // representation only
1363 Optional<std::string> ifaceid;
1364 if (params->contains("interface-id")) {
1365 ifaceid = getString(params, "interface-id");
1366 }
1367
1368 Optional<std::string> iface;
1369 if (params->contains("interface")) {
1370 iface = getString(params, "interface");
1371 }
1372
1373 // Specifying both interface for locally reachable subnets and
1374 // interface id for relays is mutually exclusive. Need to test for
1375 // this condition.
1376 if (!ifaceid.unspecified() && !iface.unspecified() && !ifaceid.empty() &&
1377 !iface.empty()) {
1378 isc_throw(isc::dhcp::DhcpConfigError,do { std::ostringstream oss__; oss__ << "parser error: interface (defined for locally reachable "
"subnets) and interface-id (defined for subnets reachable" " via relays) cannot be defined at the same time for "
"subnet " << addr << "/" << (int)len <<
"(" << params->getPosition() << ")"; throw isc
::dhcp::DhcpConfigError("parsers/dhcp_parsers.cc", 1383, oss__
.str().c_str()); } while (1)
1379 "parser error: interface (defined for locally reachable "do { std::ostringstream oss__; oss__ << "parser error: interface (defined for locally reachable "
"subnets) and interface-id (defined for subnets reachable" " via relays) cannot be defined at the same time for "
"subnet " << addr << "/" << (int)len <<
"(" << params->getPosition() << ")"; throw isc
::dhcp::DhcpConfigError("parsers/dhcp_parsers.cc", 1383, oss__
.str().c_str()); } while (1)
1380 "subnets) and interface-id (defined for subnets reachable"do { std::ostringstream oss__; oss__ << "parser error: interface (defined for locally reachable "
"subnets) and interface-id (defined for subnets reachable" " via relays) cannot be defined at the same time for "
"subnet " << addr << "/" << (int)len <<
"(" << params->getPosition() << ")"; throw isc
::dhcp::DhcpConfigError("parsers/dhcp_parsers.cc", 1383, oss__
.str().c_str()); } while (1)
1381 " via relays) cannot be defined at the same time for "do { std::ostringstream oss__; oss__ << "parser error: interface (defined for locally reachable "
"subnets) and interface-id (defined for subnets reachable" " via relays) cannot be defined at the same time for "
"subnet " << addr << "/" << (int)len <<
"(" << params->getPosition() << ")"; throw isc
::dhcp::DhcpConfigError("parsers/dhcp_parsers.cc", 1383, oss__
.str().c_str()); } while (1)
1382 "subnet " << addr << "/" << (int)len << "("do { std::ostringstream oss__; oss__ << "parser error: interface (defined for locally reachable "
"subnets) and interface-id (defined for subnets reachable" " via relays) cannot be defined at the same time for "
"subnet " << addr << "/" << (int)len <<
"(" << params->getPosition() << ")"; throw isc
::dhcp::DhcpConfigError("parsers/dhcp_parsers.cc", 1383, oss__
.str().c_str()); } while (1)
1383 << params->getPosition() << ")")do { std::ostringstream oss__; oss__ << "parser error: interface (defined for locally reachable "
"subnets) and interface-id (defined for subnets reachable" " via relays) cannot be defined at the same time for "
"subnet " << addr << "/" << (int)len <<
"(" << params->getPosition() << ")"; throw isc
::dhcp::DhcpConfigError("parsers/dhcp_parsers.cc", 1383, oss__
.str().c_str()); } while (1)
;
1384 }
1385
1386 // Configure interface-id for remote interfaces, if defined
1387 if (!ifaceid.unspecified() && !ifaceid.empty()) {
1388 std::string ifaceid_value = ifaceid.get();
1389 OptionBuffer tmp(ifaceid_value.begin(), ifaceid_value.end());
1390 OptionPtr opt(new Option(Option::V6, D6O_INTERFACE_ID, tmp));
1391 subnet6->setInterfaceId(opt);
1392 }
1393
1394 // Get interface name. If it is defined, then the subnet is available
1395 // directly over specified network interface.
1396 if (!iface.unspecified() && !iface.empty()) {
1397 if (check_iface_ && !IfaceMgr::instance().getIface(iface)) {
1398 ConstElementPtr error = params->get("interface");
1399 isc_throw(DhcpConfigError, "Specified network interface name " << ifacedo { std::ostringstream oss__; oss__ << "Specified network interface name "
<< iface << " for subnet " << subnet6->
toText() << " is not present in the system (" << error
->getPosition() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 1402, oss__.str().c_str()); } while (1)
1400 << " for subnet " << subnet6->toText()do { std::ostringstream oss__; oss__ << "Specified network interface name "
<< iface << " for subnet " << subnet6->
toText() << " is not present in the system (" << error
->getPosition() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 1402, oss__.str().c_str()); } while (1)
1401 << " is not present in the system ("do { std::ostringstream oss__; oss__ << "Specified network interface name "
<< iface << " for subnet " << subnet6->
toText() << " is not present in the system (" << error
->getPosition() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 1402, oss__.str().c_str()); } while (1)
1402 << error->getPosition() << ")")do { std::ostringstream oss__; oss__ << "Specified network interface name "
<< iface << " for subnet " << subnet6->
toText() << " is not present in the system (" << error
->getPosition() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 1402, oss__.str().c_str()); } while (1)
;
1403 }
1404
1405 subnet6->setIface(iface);
1406 }
1407
1408 // Try setting up client class.
1409 if (params->contains("client-class")) {
1410 string client_class = getString(params, "client-class");
1411 if (!client_class.empty()) {
1412 subnet6->allowClientClass(client_class);
1413 }
1414 }
1415
1416 // Setup client class list.
1417 getClientClassesElem(params, std::bind(&Network::allowClientClass,
1418 subnet6, ph::_1));
1419
1420 // Setup additional class list.
1421 getAdditionalClassesElem(params, std::bind(&Network::addAdditionalClass,
1422 subnet6, ph::_1));
1423
1424 /// client-class processing is now generic and handled in the common
1425 /// code (see isc::data::SubnetConfigParser::createSubnet)
1426
1427 // Parse t1-percent and t2-percent
1428 parseTeePercents(params, network);
1429
1430 // Parse DDNS parameters
1431 parseDdnsParams(params, network);
1432
1433 // Parse lease cache parameters
1434 parseCacheParams(params, network);
1435}
1436
1437void
1438Subnet6ConfigParser::validateResvs(const Subnet6Ptr& subnet, ConstHostPtr host) {
1439 const IPv6ResrvRange& range = host->getIPv6Reservations(IPv6Resrv::TYPE_NA);
1440 BOOST_FOREACH(auto const& it, range)if (boost::foreach_detail_::auto_any_t _foreach_col1440 = boost
::foreach_detail_::contain( (range) , (true ? nullptr : boost
::foreach_detail_::or_( boost::foreach_detail_::is_rvalue_((range
), 0) , boost::foreach_detail_::and_( boost::foreach_detail_::
not_(boost_foreach_is_noncopyable( boost::foreach_detail_::to_ptr
(range) , boost_foreach_argument_dependent_lookup_hack_value)
) , boost_foreach_is_lightweight_proxy( boost::foreach_detail_
::to_ptr(range) , boost_foreach_argument_dependent_lookup_hack_value
)))))) {} else if (boost::foreach_detail_::auto_any_t _foreach_cur1440
= boost::foreach_detail_::begin( _foreach_col1440 , (true ? nullptr
: boost::foreach_detail_::encode_type(range, boost::foreach_detail_
::is_const_(range))) , (true ? nullptr : boost::foreach_detail_
::or_( boost::foreach_detail_::is_rvalue_((range), 0) , boost
::foreach_detail_::and_( boost::foreach_detail_::not_(boost_foreach_is_noncopyable
( boost::foreach_detail_::to_ptr(range) , boost_foreach_argument_dependent_lookup_hack_value
)) , boost_foreach_is_lightweight_proxy( boost::foreach_detail_
::to_ptr(range) , boost_foreach_argument_dependent_lookup_hack_value
)))))) {} else if (boost::foreach_detail_::auto_any_t _foreach_end1440
= boost::foreach_detail_::end( _foreach_col1440 , (true ? nullptr
: boost::foreach_detail_::encode_type(range, boost::foreach_detail_
::is_const_(range))) , (true ? nullptr : boost::foreach_detail_
::or_( boost::foreach_detail_::is_rvalue_((range), 0) , boost
::foreach_detail_::and_( boost::foreach_detail_::not_(boost_foreach_is_noncopyable
( boost::foreach_detail_::to_ptr(range) , boost_foreach_argument_dependent_lookup_hack_value
)) , boost_foreach_is_lightweight_proxy( boost::foreach_detail_
::to_ptr(range) , boost_foreach_argument_dependent_lookup_hack_value
)))))) {} else for (bool _foreach_continue1440 = true; _foreach_continue1440
&& !boost::foreach_detail_::done( _foreach_cur1440 ,
_foreach_end1440 , (true ? nullptr : boost::foreach_detail_::
encode_type(range, boost::foreach_detail_::is_const_(range)))
); _foreach_continue1440 ? boost::foreach_detail_::next( _foreach_cur1440
, (true ? nullptr : boost::foreach_detail_::encode_type(range
, boost::foreach_detail_::is_const_(range)))) : (void)0) if (
boost::foreach_detail_::set_false(_foreach_continue1440)) {} else
for (auto const& it = boost::foreach_detail_::deref( _foreach_cur1440
, (true ? nullptr : boost::foreach_detail_::encode_type(range
, boost::foreach_detail_::is_const_(range)))); !_foreach_continue1440
; _foreach_continue1440 = true)
{
1441 const IOAddress& address = it.second.getPrefix();
1442 if (!subnet->inRange(address)) {
1443 isc_throw(DhcpConfigError, "specified reservation '" << addressdo { std::ostringstream oss__; oss__ << "specified reservation '"
<< address << "' is not within the IPv6 subnet '"
<< subnet->toText() << "'"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 1445, oss__.str().c_str()); } while
(1)
1444 << "' is not within the IPv6 subnet '"do { std::ostringstream oss__; oss__ << "specified reservation '"
<< address << "' is not within the IPv6 subnet '"
<< subnet->toText() << "'"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 1445, oss__.str().c_str()); } while
(1)
1445 << subnet->toText() << "'")do { std::ostringstream oss__; oss__ << "specified reservation '"
<< address << "' is not within the IPv6 subnet '"
<< subnet->toText() << "'"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 1445, oss__.str().c_str()); } while
(1)
;
1446 }
1447 }
1448}
1449
1450boost::shared_ptr<PoolsListParser>
1451Subnet6ConfigParser::createPoolsListParser() const {
1452 return (boost::make_shared<Pools6ListParser>());
1453}
1454
1455boost::shared_ptr<PdPoolsListParser>
1456Subnet6ConfigParser::createPdPoolsListParser() const {
1457 return (boost::make_shared<PdPoolsListParser>());
1458}
1459
1460//**************************** Subnet6ListConfigParser ********************
1461
1462Subnets6ListConfigParser::Subnets6ListConfigParser(bool check_iface)
1463 : check_iface_(check_iface) {
1464}
1465
1466size_t
1467Subnets6ListConfigParser::parse(SrvConfigPtr cfg,
1468 ConstElementPtr subnets_list,
1469 bool encapsulate_options) {
1470 size_t cnt = 0;
1471 for (auto const& subnet_json : subnets_list->listValue()) {
1472
1473 auto const& parser = createSubnetConfigParser();
1474 Subnet6Ptr subnet = parser->parse(subnet_json, encapsulate_options);
1475
1476 // Adding a subnet to the Configuration Manager may fail if the
1477 // subnet id is invalid (duplicate). Thus, we catch exceptions
1478 // here to append a position in the configuration string.
1479 try {
1480 cfg->getCfgSubnets6()->add(subnet);
1481 cnt++;
1482 } catch (const std::exception& ex) {
1483 isc_throw(DhcpConfigError, ex.what() << " ("do { std::ostringstream oss__; oss__ << ex.what() <<
" (" << subnet_json->getPosition() << ")"; throw
DhcpConfigError("parsers/dhcp_parsers.cc", 1484, oss__.str()
.c_str()); } while (1)
1484 << subnet_json->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() <<
" (" << subnet_json->getPosition() << ")"; throw
DhcpConfigError("parsers/dhcp_parsers.cc", 1484, oss__.str()
.c_str()); } while (1)
;
1485 }
1486 }
1487 return (cnt);
1488}
1489
1490size_t
1491Subnets6ListConfigParser::parse(Subnet6Collection& subnets,
1492 ConstElementPtr subnets_list,
1493 bool encapsulate_options) {
1494 size_t cnt = 0;
1495 for (auto const& subnet_json : subnets_list->listValue()) {
1496
1497 auto const& parser = createSubnetConfigParser();
1498 Subnet6Ptr subnet = parser->parse(subnet_json, encapsulate_options);
1499 if (subnet) {
1500 try {
1501 auto ret = subnets.insert(subnet);
1502 if (!ret.second) {
1503 isc_throw(Unexpected,do { std::ostringstream oss__; oss__ << "can't store subnet because of conflict"
; throw Unexpected("parsers/dhcp_parsers.cc", 1504, oss__.str
().c_str()); } while (1)
1504 "can't store subnet because of conflict")do { std::ostringstream oss__; oss__ << "can't store subnet because of conflict"
; throw Unexpected("parsers/dhcp_parsers.cc", 1504, oss__.str
().c_str()); } while (1)
;
1505 }
1506 ++cnt;
1507 } catch (const std::exception& ex) {
1508 isc_throw(DhcpConfigError, ex.what() << " ("do { std::ostringstream oss__; oss__ << ex.what() <<
" (" << subnet_json->getPosition() << ")"; throw
DhcpConfigError("parsers/dhcp_parsers.cc", 1509, oss__.str()
.c_str()); } while (1)
1509 << subnet_json->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() <<
" (" << subnet_json->getPosition() << ")"; throw
DhcpConfigError("parsers/dhcp_parsers.cc", 1509, oss__.str()
.c_str()); } while (1)
;
1510 }
1511 }
1512 }
1513 return (cnt);
1514}
1515
1516boost::shared_ptr<Subnet6ConfigParser>
1517Subnets6ListConfigParser::createSubnetConfigParser() const {
1518 return (boost::make_shared<Subnet6ConfigParser>(check_iface_));
1519}
1520
1521//**************************** D2ClientConfigParser **********************
1522
1523dhcp_ddns::NameChangeProtocol
1524D2ClientConfigParser::getProtocol(ConstElementPtr scope,
1525 const std::string& name) {
1526 return (getAndConvert<dhcp_ddns::NameChangeProtocol,
1527 dhcp_ddns::stringToNcrProtocol>
1528 (scope, name, "NameChangeRequest protocol"));
1529}
1530
1531dhcp_ddns::NameChangeFormat
1532D2ClientConfigParser::getFormat(ConstElementPtr scope,
1533 const std::string& name) {
1534 return (getAndConvert<dhcp_ddns::NameChangeFormat,
1535 dhcp_ddns::stringToNcrFormat>
1536 (scope, name, "NameChangeRequest format"));
1537}
1538
1539D2ClientConfig::ReplaceClientNameMode
1540D2ClientConfigParser::getMode(ConstElementPtr scope,
1541 const std::string& name) {
1542 return (getAndConvert<D2ClientConfig::ReplaceClientNameMode,
1543 D2ClientConfig::stringToReplaceClientNameMode>
1544 (scope, name, "ReplaceClientName mode"));
1545}
1546
1547D2ClientConfigPtr
1548D2ClientConfigParser::parse(isc::data::ConstElementPtr client_config) {
1549 D2ClientConfigPtr new_config;
1550
1551 // Get all parameters that are needed to create the D2ClientConfig.
1552 bool enable_updates = getBoolean(client_config, "enable-updates");
1553
1554 IOAddress server_ip = getAddress(client_config, "server-ip");
1555
1556 uint32_t server_port = getUint32(client_config, "server-port");
1557
1558 std::string sender_ip_str = getString(client_config, "sender-ip");
1559
1560 uint32_t sender_port = getUint32(client_config, "sender-port");
1561
1562 uint32_t max_queue_size = getUint32(client_config, "max-queue-size");
1563
1564 dhcp_ddns::NameChangeProtocol ncr_protocol =
1565 getProtocol(client_config, "ncr-protocol");
1566
1567 dhcp_ddns::NameChangeFormat ncr_format =
1568 getFormat(client_config, "ncr-format");
1569
1570 IOAddress sender_ip(0);
1571 if (sender_ip_str.empty()) {
1572 // The default sender IP depends on the server IP family
1573 sender_ip = (server_ip.isV4() ? IOAddress::IPV4_ZERO_ADDRESS() :
1574 IOAddress::IPV6_ZERO_ADDRESS());
1575 } else {
1576 try {
1577 sender_ip = IOAddress(sender_ip_str);
1578 } catch (const std::exception& ex) {
1579 isc_throw(DhcpConfigError, "invalid address (" << sender_ip_strdo { std::ostringstream oss__; oss__ << "invalid address ("
<< sender_ip_str << ") specified for parameter 'sender-ip' ("
<< getPosition("sender-ip", client_config) << ")"
; throw DhcpConfigError("parsers/dhcp_parsers.cc", 1581, oss__
.str().c_str()); } while (1)
1580 << ") specified for parameter 'sender-ip' ("do { std::ostringstream oss__; oss__ << "invalid address ("
<< sender_ip_str << ") specified for parameter 'sender-ip' ("
<< getPosition("sender-ip", client_config) << ")"
; throw DhcpConfigError("parsers/dhcp_parsers.cc", 1581, oss__
.str().c_str()); } while (1)
1581 << getPosition("sender-ip", client_config) << ")")do { std::ostringstream oss__; oss__ << "invalid address ("
<< sender_ip_str << ") specified for parameter 'sender-ip' ("
<< getPosition("sender-ip", client_config) << ")"
; throw DhcpConfigError("parsers/dhcp_parsers.cc", 1581, oss__
.str().c_str()); } while (1)
;
1582 }
1583 }
1584
1585 // Now we check for logical errors. This repeats what is done in
1586 // D2ClientConfig::validate(), but doing it here permits us to
1587 // emit meaningful parameter position info in the error.
1588 if (ncr_format != dhcp_ddns::FMT_JSON) {
1589 isc_throw(D2ClientError, "D2ClientConfig error: NCR Format: "do { std::ostringstream oss__; oss__ << "D2ClientConfig error: NCR Format: "
<< dhcp_ddns::ncrFormatToString(ncr_format) << " is not supported. ("
<< getPosition("ncr-format", client_config) << ")"
; throw D2ClientError("parsers/dhcp_parsers.cc", 1592, oss__.
str().c_str()); } while (1)
1590 << dhcp_ddns::ncrFormatToString(ncr_format)do { std::ostringstream oss__; oss__ << "D2ClientConfig error: NCR Format: "
<< dhcp_ddns::ncrFormatToString(ncr_format) << " is not supported. ("
<< getPosition("ncr-format", client_config) << ")"
; throw D2ClientError("parsers/dhcp_parsers.cc", 1592, oss__.
str().c_str()); } while (1)
1591 << " is not supported. ("do { std::ostringstream oss__; oss__ << "D2ClientConfig error: NCR Format: "
<< dhcp_ddns::ncrFormatToString(ncr_format) << " is not supported. ("
<< getPosition("ncr-format", client_config) << ")"
; throw D2ClientError("parsers/dhcp_parsers.cc", 1592, oss__.
str().c_str()); } while (1)
1592 << getPosition("ncr-format", client_config) << ")")do { std::ostringstream oss__; oss__ << "D2ClientConfig error: NCR Format: "
<< dhcp_ddns::ncrFormatToString(ncr_format) << " is not supported. ("
<< getPosition("ncr-format", client_config) << ")"
; throw D2ClientError("parsers/dhcp_parsers.cc", 1592, oss__.
str().c_str()); } while (1)
;
1593 }
1594
1595 if (ncr_protocol != dhcp_ddns::NCR_UDP) {
1596 isc_throw(D2ClientError, "D2ClientConfig error: NCR Protocol: "do { std::ostringstream oss__; oss__ << "D2ClientConfig error: NCR Protocol: "
<< dhcp_ddns::ncrProtocolToString(ncr_protocol) <<
" is not supported. (" << getPosition("ncr-protocol", client_config
) << ")"; throw D2ClientError("parsers/dhcp_parsers.cc"
, 1599, oss__.str().c_str()); } while (1)
1597 << dhcp_ddns::ncrProtocolToString(ncr_protocol)do { std::ostringstream oss__; oss__ << "D2ClientConfig error: NCR Protocol: "
<< dhcp_ddns::ncrProtocolToString(ncr_protocol) <<
" is not supported. (" << getPosition("ncr-protocol", client_config
) << ")"; throw D2ClientError("parsers/dhcp_parsers.cc"
, 1599, oss__.str().c_str()); } while (1)
1598 << " is not supported. ("do { std::ostringstream oss__; oss__ << "D2ClientConfig error: NCR Protocol: "
<< dhcp_ddns::ncrProtocolToString(ncr_protocol) <<
" is not supported. (" << getPosition("ncr-protocol", client_config
) << ")"; throw D2ClientError("parsers/dhcp_parsers.cc"
, 1599, oss__.str().c_str()); } while (1)
1599 << getPosition("ncr-protocol", client_config) << ")")do { std::ostringstream oss__; oss__ << "D2ClientConfig error: NCR Protocol: "
<< dhcp_ddns::ncrProtocolToString(ncr_protocol) <<
" is not supported. (" << getPosition("ncr-protocol", client_config
) << ")"; throw D2ClientError("parsers/dhcp_parsers.cc"
, 1599, oss__.str().c_str()); } while (1)
;
1600 }
1601
1602 if (sender_ip.getFamily() != server_ip.getFamily()) {
1603 isc_throw(D2ClientError,do { std::ostringstream oss__; oss__ << "D2ClientConfig error: address family mismatch: "
<< "server-ip: " << server_ip.toText() << " is: "
<< (server_ip.isV4() ? "IPv4" : "IPv6") << " while sender-ip: "
<< sender_ip.toText() << " is: " << (sender_ip
.isV4() ? "IPv4" : "IPv6") << " (" << getPosition
("sender-ip", client_config) << ")"; throw D2ClientError
("parsers/dhcp_parsers.cc", 1609, oss__.str().c_str()); } while
(1)
1604 "D2ClientConfig error: address family mismatch: "do { std::ostringstream oss__; oss__ << "D2ClientConfig error: address family mismatch: "
<< "server-ip: " << server_ip.toText() << " is: "
<< (server_ip.isV4() ? "IPv4" : "IPv6") << " while sender-ip: "
<< sender_ip.toText() << " is: " << (sender_ip
.isV4() ? "IPv4" : "IPv6") << " (" << getPosition
("sender-ip", client_config) << ")"; throw D2ClientError
("parsers/dhcp_parsers.cc", 1609, oss__.str().c_str()); } while
(1)
1605 << "server-ip: " << server_ip.toText()do { std::ostringstream oss__; oss__ << "D2ClientConfig error: address family mismatch: "
<< "server-ip: " << server_ip.toText() << " is: "
<< (server_ip.isV4() ? "IPv4" : "IPv6") << " while sender-ip: "
<< sender_ip.toText() << " is: " << (sender_ip
.isV4() ? "IPv4" : "IPv6") << " (" << getPosition
("sender-ip", client_config) << ")"; throw D2ClientError
("parsers/dhcp_parsers.cc", 1609, oss__.str().c_str()); } while
(1)
1606 << " is: " << (server_ip.isV4() ? "IPv4" : "IPv6")do { std::ostringstream oss__; oss__ << "D2ClientConfig error: address family mismatch: "
<< "server-ip: " << server_ip.toText() << " is: "
<< (server_ip.isV4() ? "IPv4" : "IPv6") << " while sender-ip: "
<< sender_ip.toText() << " is: " << (sender_ip
.isV4() ? "IPv4" : "IPv6") << " (" << getPosition
("sender-ip", client_config) << ")"; throw D2ClientError
("parsers/dhcp_parsers.cc", 1609, oss__.str().c_str()); } while
(1)
1607 << " while sender-ip: " << sender_ip.toText()do { std::ostringstream oss__; oss__ << "D2ClientConfig error: address family mismatch: "
<< "server-ip: " << server_ip.toText() << " is: "
<< (server_ip.isV4() ? "IPv4" : "IPv6") << " while sender-ip: "
<< sender_ip.toText() << " is: " << (sender_ip
.isV4() ? "IPv4" : "IPv6") << " (" << getPosition
("sender-ip", client_config) << ")"; throw D2ClientError
("parsers/dhcp_parsers.cc", 1609, oss__.str().c_str()); } while
(1)
1608 << " is: " << (sender_ip.isV4() ? "IPv4" : "IPv6")do { std::ostringstream oss__; oss__ << "D2ClientConfig error: address family mismatch: "
<< "server-ip: " << server_ip.toText() << " is: "
<< (server_ip.isV4() ? "IPv4" : "IPv6") << " while sender-ip: "
<< sender_ip.toText() << " is: " << (sender_ip
.isV4() ? "IPv4" : "IPv6") << " (" << getPosition
("sender-ip", client_config) << ")"; throw D2ClientError
("parsers/dhcp_parsers.cc", 1609, oss__.str().c_str()); } while
(1)
1609 << " (" << getPosition("sender-ip", client_config) << ")")do { std::ostringstream oss__; oss__ << "D2ClientConfig error: address family mismatch: "
<< "server-ip: " << server_ip.toText() << " is: "
<< (server_ip.isV4() ? "IPv4" : "IPv6") << " while sender-ip: "
<< sender_ip.toText() << " is: " << (sender_ip
.isV4() ? "IPv4" : "IPv6") << " (" << getPosition
("sender-ip", client_config) << ")"; throw D2ClientError
("parsers/dhcp_parsers.cc", 1609, oss__.str().c_str()); } while
(1)
;
1610 }
1611
1612 if (server_ip == sender_ip && server_port == sender_port) {
1613 isc_throw(D2ClientError,do { std::ostringstream oss__; oss__ << "D2ClientConfig error: server and sender cannot"
" share the exact same IP address/port: " << server_ip
.toText() << "/" << server_port << " (" <<
getPosition("sender-ip", client_config) << ")"; throw D2ClientError
("parsers/dhcp_parsers.cc", 1617, oss__.str().c_str()); } while
(1)
1614 "D2ClientConfig error: server and sender cannot"do { std::ostringstream oss__; oss__ << "D2ClientConfig error: server and sender cannot"
" share the exact same IP address/port: " << server_ip
.toText() << "/" << server_port << " (" <<
getPosition("sender-ip", client_config) << ")"; throw D2ClientError
("parsers/dhcp_parsers.cc", 1617, oss__.str().c_str()); } while
(1)
1615 " share the exact same IP address/port: "do { std::ostringstream oss__; oss__ << "D2ClientConfig error: server and sender cannot"
" share the exact same IP address/port: " << server_ip
.toText() << "/" << server_port << " (" <<
getPosition("sender-ip", client_config) << ")"; throw D2ClientError
("parsers/dhcp_parsers.cc", 1617, oss__.str().c_str()); } while
(1)
1616 << server_ip.toText() << "/" << server_portdo { std::ostringstream oss__; oss__ << "D2ClientConfig error: server and sender cannot"
" share the exact same IP address/port: " << server_ip
.toText() << "/" << server_port << " (" <<
getPosition("sender-ip", client_config) << ")"; throw D2ClientError
("parsers/dhcp_parsers.cc", 1617, oss__.str().c_str()); } while
(1)
1617 << " (" << getPosition("sender-ip", client_config) << ")")do { std::ostringstream oss__; oss__ << "D2ClientConfig error: server and sender cannot"
" share the exact same IP address/port: " << server_ip
.toText() << "/" << server_port << " (" <<
getPosition("sender-ip", client_config) << ")"; throw D2ClientError
("parsers/dhcp_parsers.cc", 1617, oss__.str().c_str()); } while
(1)
;
1618 }
1619
1620 try {
1621 // Attempt to create the new client config.
1622 new_config.reset(new D2ClientConfig(enable_updates,
1623 server_ip,
1624 server_port,
1625 sender_ip,
1626 sender_port,
1627 max_queue_size,
1628 ncr_protocol,
1629 ncr_format));
1630 } catch (const std::exception& ex) {
1631 isc_throw(DhcpConfigError, ex.what() << " ("do { std::ostringstream oss__; oss__ << ex.what() <<
" (" << client_config->getPosition() << ")"; throw
DhcpConfigError("parsers/dhcp_parsers.cc", 1632, oss__.str()
.c_str()); } while (1)
1632 << client_config->getPosition() << ")")do { std::ostringstream oss__; oss__ << ex.what() <<
" (" << client_config->getPosition() << ")"; throw
DhcpConfigError("parsers/dhcp_parsers.cc", 1632, oss__.str()
.c_str()); } while (1)
;
1633 }
1634
1635 // Add user context
1636 ConstElementPtr user_context = client_config->get("user-context");
1637 if (user_context) {
1638 new_config->setContext(user_context);
1639 }
1640
1641 return (new_config);
1642}
1643
1644/// @brief This table defines default values for D2 client configuration
1645const SimpleDefaults D2ClientConfigParser::D2_CLIENT_CONFIG_DEFAULTS = {
1646 // enable-updates is unconditionally required
1647 { "server-ip", Element::string, "127.0.0.1" },
1648 { "server-port", Element::integer, "53001" },
1649 // default sender-ip depends on server-ip family, so we leave default blank
1650 // parser knows to use the appropriate ZERO address based on server-ip
1651 { "sender-ip", Element::string, "" },
1652 { "sender-port", Element::integer, "0" },
1653 { "max-queue-size", Element::integer, "1024" },
1654 { "ncr-protocol", Element::string, "UDP" },
1655 { "ncr-format", Element::string, "JSON" }
1656};
1657
1658size_t
1659D2ClientConfigParser::setAllDefaults(isc::data::ConstElementPtr d2_config) {
1660 ElementPtr mutable_d2 = boost::const_pointer_cast<Element>(d2_config);
1661 return (SimpleParser::setDefaults(mutable_d2, D2_CLIENT_CONFIG_DEFAULTS));
1662}
1663
1664void
1665CompatibilityParser::parse(ConstElementPtr compatibility, SrvConfig& srv_cfg) {
1666 if (compatibility) {
1667 auto family = CfgMgr::instance().getFamily();
1668 for (auto const& kv : compatibility->mapValue()) {
1669 if (!kv.second || (kv.second->getType() != Element::boolean)) {
1670 isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "compatibility parameter values must be "
<< "boolean (" << kv.first << " at " <<
kv.second->getPosition() << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 1673, oss__.str().c_str()); } while
(1)
1671 "compatibility parameter values must be "do { std::ostringstream oss__; oss__ << "compatibility parameter values must be "
<< "boolean (" << kv.first << " at " <<
kv.second->getPosition() << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 1673, oss__.str().c_str()); } while
(1)
1672 << "boolean (" << kv.first << " at "do { std::ostringstream oss__; oss__ << "compatibility parameter values must be "
<< "boolean (" << kv.first << " at " <<
kv.second->getPosition() << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 1673, oss__.str().c_str()); } while
(1)
1673 << kv.second->getPosition() << ")")do { std::ostringstream oss__; oss__ << "compatibility parameter values must be "
<< "boolean (" << kv.first << " at " <<
kv.second->getPosition() << ")"; throw DhcpConfigError
("parsers/dhcp_parsers.cc", 1673, oss__.str().c_str()); } while
(1)
;
1674 }
1675 if (kv.first == "lenient-option-parsing") {
1676 srv_cfg.setLenientOptionParsing(kv.second->boolValue());
1677 } else if (family == AF_INET2) {
1678 if (kv.first == "ignore-dhcp-server-identifier") {
1679 srv_cfg.setIgnoreServerIdentifier(kv.second->boolValue());
1680 } else if (kv.first == "ignore-rai-link-selection") {
1681 srv_cfg.setIgnoreRAILinkSelection(kv.second->boolValue());
1682 } else if (kv.first == "exclude-first-last-24") {
1683 srv_cfg.setExcludeFirstLast24(kv.second->boolValue());
1684 } else {
1685 isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "unsupported compatibility parameter: "
<< kv.first << " (" << kv.second->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 1688, oss__.str().c_str()); } while (1)
1686 "unsupported compatibility parameter: "do { std::ostringstream oss__; oss__ << "unsupported compatibility parameter: "
<< kv.first << " (" << kv.second->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 1688, oss__.str().c_str()); } while (1)
1687 << kv.first << " (" << kv.second->getPosition()do { std::ostringstream oss__; oss__ << "unsupported compatibility parameter: "
<< kv.first << " (" << kv.second->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 1688, oss__.str().c_str()); } while (1)
1688 << ")")do { std::ostringstream oss__; oss__ << "unsupported compatibility parameter: "
<< kv.first << " (" << kv.second->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 1688, oss__.str().c_str()); } while (1)
;
1689 }
1690 } else {
1691 isc_throw(DhcpConfigError,do { std::ostringstream oss__; oss__ << "unsupported compatibility parameter: "
<< kv.first << " (" << kv.second->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 1694, oss__.str().c_str()); } while (1)
1692 "unsupported compatibility parameter: "do { std::ostringstream oss__; oss__ << "unsupported compatibility parameter: "
<< kv.first << " (" << kv.second->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 1694, oss__.str().c_str()); } while (1)
1693 << kv.first << " (" << kv.second->getPosition()do { std::ostringstream oss__; oss__ << "unsupported compatibility parameter: "
<< kv.first << " (" << kv.second->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 1694, oss__.str().c_str()); } while (1)
1694 << ")")do { std::ostringstream oss__; oss__ << "unsupported compatibility parameter: "
<< kv.first << " (" << kv.second->getPosition
() << ")"; throw DhcpConfigError("parsers/dhcp_parsers.cc"
, 1694, oss__.str().c_str()); } while (1)
;
1695 }
1696 }
1697 }
1698}
1699
1700} // namespace dhcp
1701} // namespace isc