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 |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |
36 | using namespace std; |
37 | using namespace isc::asiolink; |
38 | using namespace isc::data; |
39 | using namespace isc::util; |
40 | namespace ph = std::placeholders; |
41 | |
42 | namespace isc { |
43 | namespace dhcp { |
44 | |
45 | // ******************** MACSourcesListConfigParser ************************* |
46 | |
47 | void |
48 | MACSourcesListConfigParser::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 ************************* |
78 | void 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 | |
131 | OptionDefParser::OptionDefParser(const uint16_t address_family) |
132 | : address_family_(address_family) { |
133 | } |
134 | |
135 | OptionDefinitionPtr |
136 | OptionDefParser::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 | |
273 | OptionDefListParser::OptionDefListParser(const uint16_t address_family) |
274 | : address_family_(address_family) { |
275 | } |
276 | |
277 | void |
278 | OptionDefListParser::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 ******************************** |
304 | RelayInfoParser::RelayInfoParser(const Option::Universe& family) |
305 | : family_(family) { |
306 | }; |
307 | |
308 | void |
309 | RelayInfoParser::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 | |
335 | void |
336 | RelayInfoParser::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 | |
372 | void |
373 | PoolParser::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 | |
537 | boost::shared_ptr<OptionDataListParser> |
538 | PoolParser::createOptionDataListParser(const uint16_t address_family) const { |
539 | return (boost::make_shared<OptionDataListParser>(address_family)); |
540 | } |
541 | |
542 | //****************************** Pool4Parser ************************* |
543 | |
544 | PoolPtr |
545 | Pool4Parser::poolMaker (IOAddress &addr, uint32_t len, int32_t) { |
546 | return (PoolPtr(new Pool4(addr, len))); |
547 | } |
548 | |
549 | PoolPtr |
550 | Pool4Parser::poolMaker (IOAddress &min, IOAddress &max, int32_t) { |
551 | return (PoolPtr(new Pool4(min, max))); |
552 | } |
553 | |
554 | //****************************** Pools4ListParser ************************* |
555 | |
556 | void |
557 | Pools4ListParser::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 | |
565 | boost::shared_ptr<PoolParser> |
566 | Pools4ListParser::createPoolConfigParser() const { |
567 | return (boost::make_shared<Pool4Parser>()); |
568 | } |
569 | |
570 | //****************************** SubnetConfigParser ************************* |
571 | |
572 | SubnetConfigParser::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 | |
579 | SubnetPtr |
580 | SubnetConfigParser::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 | |
612 | void |
613 | SubnetConfigParser::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 | |
698 | boost::shared_ptr<OptionDataListParser> |
699 | SubnetConfigParser::createOptionDataListParser() const { |
700 | return (boost::make_shared<OptionDataListParser>(address_family_)); |
701 | } |
702 | |
703 | //****************************** Subnet4ConfigParser ************************* |
704 | |
705 | Subnet4ConfigParser::Subnet4ConfigParser(bool check_iface) |
706 | : SubnetConfigParser(AF_INET2, check_iface) { |
707 | } |
708 | |
709 | Subnet4Ptr |
710 | Subnet4ConfigParser::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 | |
764 | void |
765 | Subnet4ConfigParser::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 | |
978 | void |
979 | Subnet4ConfigParser::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 | |
988 | boost::shared_ptr<PoolsListParser> |
989 | Subnet4ConfigParser::createPoolsListParser() const { |
990 | return (boost::make_shared<Pools4ListParser>()); |
991 | } |
992 | |
993 | //**************************** Subnets4ListConfigParser ********************** |
994 | |
995 | Subnets4ListConfigParser::Subnets4ListConfigParser(bool check_iface) |
996 | : check_iface_(check_iface) { |
997 | } |
998 | |
999 | size_t |
1000 | Subnets4ListConfigParser::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 | |
1025 | size_t |
1026 | Subnets4ListConfigParser::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 | |
1051 | boost::shared_ptr<Subnet4ConfigParser> |
1052 | Subnets4ListConfigParser::createSubnetConfigParser() const { |
1053 | return (boost::make_shared<Subnet4ConfigParser>(check_iface_)); |
1054 | } |
1055 | |
1056 | //**************************** Pool6Parser ********************************* |
1057 | |
1058 | PoolPtr |
1059 | Pool6Parser::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 | |
1065 | PoolPtr |
1066 | Pool6Parser::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 | |
1075 | void |
1076 | Pools6ListParser::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 | |
1084 | boost::shared_ptr<PoolParser> |
1085 | Pools6ListParser::createPoolConfigParser() const { |
1086 | return (boost::make_shared<Pool6Parser>()); |
1087 | } |
1088 | |
1089 | //**************************** PdPoolParser ****************************** |
1090 | |
1091 | PdPoolParser::PdPoolParser() { |
1092 | } |
1093 | |
1094 | void |
1095 | PdPoolParser::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 | |
1193 | boost::shared_ptr<OptionDataListParser> |
1194 | PdPoolParser::createOptionDataListParser() const { |
1195 | return (boost::make_shared<OptionDataListParser>(AF_INET610)); |
1196 | } |
1197 | |
1198 | //**************************** PdPoolsListParser ************************ |
1199 | |
1200 | void |
1201 | PdPoolsListParser::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 | |
1209 | boost::shared_ptr<PdPoolParser> |
1210 | PdPoolsListParser::createPdPoolConfigParser() const { |
1211 | return (boost::make_shared<PdPoolParser>()); |
1212 | } |
1213 | |
1214 | //**************************** Subnet6ConfigParser *********************** |
1215 | |
1216 | Subnet6ConfigParser::Subnet6ConfigParser(bool check_iface) |
1217 | : SubnetConfigParser(AF_INET610, check_iface) { |
1218 | } |
1219 | |
1220 | Subnet6Ptr |
1221 | Subnet6ConfigParser::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? |
1285 | void |
1286 | Subnet6ConfigParser::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 | |
1292 | void |
1293 | Subnet6ConfigParser::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 | |
1437 | void |
1438 | Subnet6ConfigParser::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 | |
1450 | boost::shared_ptr<PoolsListParser> |
1451 | Subnet6ConfigParser::createPoolsListParser() const { |
1452 | return (boost::make_shared<Pools6ListParser>()); |
1453 | } |
1454 | |
1455 | boost::shared_ptr<PdPoolsListParser> |
1456 | Subnet6ConfigParser::createPdPoolsListParser() const { |
1457 | return (boost::make_shared<PdPoolsListParser>()); |
1458 | } |
1459 | |
1460 | //**************************** Subnet6ListConfigParser ******************** |
1461 | |
1462 | Subnets6ListConfigParser::Subnets6ListConfigParser(bool check_iface) |
1463 | : check_iface_(check_iface) { |
1464 | } |
1465 | |
1466 | size_t |
1467 | Subnets6ListConfigParser::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 | |
1490 | size_t |
1491 | Subnets6ListConfigParser::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 | |
1516 | boost::shared_ptr<Subnet6ConfigParser> |
1517 | Subnets6ListConfigParser::createSubnetConfigParser() const { |
1518 | return (boost::make_shared<Subnet6ConfigParser>(check_iface_)); |
1519 | } |
1520 | |
1521 | //**************************** D2ClientConfigParser ********************** |
1522 | |
1523 | dhcp_ddns::NameChangeProtocol |
1524 | D2ClientConfigParser::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 | |
1531 | dhcp_ddns::NameChangeFormat |
1532 | D2ClientConfigParser::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 | |
1539 | D2ClientConfig::ReplaceClientNameMode |
1540 | D2ClientConfigParser::getMode(ConstElementPtr scope, |
1541 | const std::string& name) { |
1542 | return (getAndConvert<D2ClientConfig::ReplaceClientNameMode, |
1543 | D2ClientConfig::stringToReplaceClientNameMode> |
1544 | (scope, name, "ReplaceClientName mode")); |
1545 | } |
1546 | |
1547 | D2ClientConfigPtr |
1548 | D2ClientConfigParser::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 |
1645 | const 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 | |
1658 | size_t |
1659 | D2ClientConfigParser::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 | |
1664 | void |
1665 | CompatibilityParser::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 |