Kea 2.5.5
shared_network_parser.cc
Go to the documentation of this file.
1// Copyright (C) 2017-2023 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
10#include <cc/data.h>
11#include <dhcpsrv/cfgmgr.h>
12#include <dhcpsrv/cfg_option.h>
18#include <boost/make_shared.hpp>
19#include <boost/pointer_cast.hpp>
20#include <string>
21
22using namespace isc::asiolink;
23using namespace isc::data;
24using namespace isc::util;
25
26namespace isc {
27namespace dhcp {
28
30 : check_iface_(check_iface) {
31}
32
35 bool encapsulate_options) {
36 SharedNetwork4Ptr shared_network;
37 try {
38
39 // Check parameters.
41 shared_network_data);
42
43 // Make sure that the network name has been specified. The name is required
44 // to create a SharedNetwork4 object.
45 std::string name = getString(shared_network_data, "name");
46 shared_network.reset(new SharedNetwork4(name));
47
48 // Move from reservation mode to new reservations flags.
49 ElementPtr mutable_params;
50 mutable_params = boost::const_pointer_cast<Element>(shared_network_data);
52
53 // Parse parameters common to all Network derivations.
54 NetworkPtr network = boost::dynamic_pointer_cast<Network>(shared_network);
55 parseCommon(mutable_params, network);
56
57 // interface is an optional parameter
58 if (shared_network_data->contains("interface")) {
59 std::string iface = getString(shared_network_data, "interface");
60 if (!iface.empty()) {
61 if (check_iface_ && !IfaceMgr::instance().getIface(iface)) {
63 shared_network_data->get("interface");
65 "Specified network interface name " << iface
66 << " for shared network " << name
67 << " is not present in the system ("
68 << error->getPosition() << ")");
69 }
70 shared_network->setIface(iface);
71 }
72 }
73
74 if (shared_network_data->contains("option-data")) {
75 auto json = shared_network_data->get("option-data");
76 // Create parser instance for option-data.
77 CfgOptionPtr cfg_option = shared_network->getCfgOption();
78 auto parser = createOptionDataListParser();
79 parser->parse(cfg_option, json, encapsulate_options);
80 }
81
82 if (shared_network_data->contains("subnet4")) {
83 auto json = shared_network_data->get("subnet4");
84
85 // Create parser instance of subnet4.
86 auto parser = createSubnetsListParser();
87 Subnet4Collection subnets;
88 parser->parse(subnets, json);
89
90 // Add all returned subnets into shared network.
91 for (auto subnet = subnets.cbegin(); subnet != subnets.cend();
92 ++subnet) {
93 shared_network->add(*subnet);
94 }
95 }
96
97 if (shared_network_data->contains("match-client-id")) {
98 shared_network->setMatchClientId(getBoolean(shared_network_data,
99 "match-client-id"));
100 }
101
102 if (shared_network_data->contains("authoritative")) {
103 shared_network->setAuthoritative(getBoolean(shared_network_data,
104 "authoritative"));
105 }
106
107 // Set next-server
108 if (shared_network_data->contains("next-server")) {
109 std::string next_server;
110 try {
111 next_server = getString(shared_network_data, "next-server");
112 if (!next_server.empty()) {
113 shared_network->setSiaddr(IOAddress(next_server));
114 }
115 } catch (...) {
116 ConstElementPtr next = shared_network_data->get("next-server");
117 std::string pos;
118 if (next) {
119 pos = next->getPosition().str();
120 } else {
121 pos = shared_network_data->getPosition().str();
122 }
123 isc_throw(DhcpConfigError, "invalid parameter next-server : "
124 << next_server << "(" << pos << ")");
125 }
126 }
127
128 // Set server-hostname.
129 if (shared_network_data->contains("server-hostname")) {
130 std::string sname = getString(shared_network_data, "server-hostname");
131 if (!sname.empty()) {
132 if (sname.length() >= Pkt4::MAX_SNAME_LEN) {
133 ConstElementPtr error = shared_network_data->get("server-hostname");
134 isc_throw(DhcpConfigError, "server-hostname must be at most "
135 << Pkt4::MAX_SNAME_LEN - 1 << " bytes long, it is "
136 << sname.length() << " ("
137 << error->getPosition() << ")");
138 }
139 shared_network->setSname(sname);
140 }
141 }
142
143 // Set boot-file-name.
144 if (shared_network_data->contains("boot-file-name")) {
145 std::string filename = getString(shared_network_data, "boot-file-name");
146 if (!filename.empty()) {
147 if (filename.length() > Pkt4::MAX_FILE_LEN) {
148 ConstElementPtr error = shared_network_data->get("boot-file-name");
149 isc_throw(DhcpConfigError, "boot-file-name must be at most "
150 << Pkt4::MAX_FILE_LEN - 1 << " bytes long, it is "
151 << filename.length() << " ("
152 << error->getPosition() << ")");
153 }
154 shared_network->setFilename(filename);
155 }
156 }
157
158 if (shared_network_data->contains("client-class")) {
159 std::string client_class = getString(shared_network_data, "client-class");
160 if (!client_class.empty()) {
161 shared_network->allowClientClass(client_class);
162 }
163 }
164
165 ConstElementPtr user_context = shared_network_data->get("user-context");
166 if (user_context) {
167 shared_network->setContext(user_context);
168 }
169
170 if (shared_network_data->contains("require-client-classes")) {
171 const std::vector<data::ElementPtr>& class_list =
172 shared_network_data->get("require-client-classes")->listValue();
173 for (auto cclass = class_list.cbegin();
174 cclass != class_list.cend(); ++cclass) {
175 if (((*cclass)->getType() != Element::string) ||
176 (*cclass)->stringValue().empty()) {
177 isc_throw(DhcpConfigError, "invalid class name ("
178 << (*cclass)->getPosition() << ")");
179 }
180 shared_network->requireClientClass((*cclass)->stringValue());
181 }
182 }
183
184 if (shared_network_data->contains("relay")) {
185 auto relay_parms = shared_network_data->get("relay");
186 if (relay_parms) {
189 parser.parse(relay_info, relay_parms);
190 shared_network->setRelayInfo(*relay_info);
191 }
192 }
193
194 parseTeePercents(shared_network_data, network);
195
196 // Parse DDNS parameters
197 parseDdnsParams(shared_network_data, network);
198
199 // Parse lease cache parameters
200 parseCacheParams(shared_network_data, network);
201
202 // Parse allocator params.
203 parseAllocatorParams(shared_network_data, network);
204
205 // Parse offer-lifetime parameter.
206 Network4Ptr network4 = boost::dynamic_pointer_cast<Network4>(shared_network);
207 parseOfferLft(shared_network_data, network4);
208
209 } catch (const DhcpConfigError&) {
210 // Position was already added
211 throw;
212 } catch (const std::exception& ex) {
213 isc_throw(DhcpConfigError, ex.what() << " ("
214 << shared_network_data->getPosition() << ")");
215 }
216
217 // In order to take advantage of the dynamic inheritance of global
218 // parameters to a shared network we need to set a callback function
219 // for each shared network to allow for fetching global parameters.
220 shared_network->setFetchGlobalsFn([]() -> ConstCfgGlobalsPtr {
221 return (CfgMgr::instance().getCurrentCfg()->getConfiguredGlobals());
222 });
223
224 return (shared_network);
225}
226
227boost::shared_ptr<OptionDataListParser>
229 auto parser = boost::make_shared<OptionDataListParser>(AF_INET);
230 return (parser);
231}
232
233boost::shared_ptr<Subnets4ListConfigParser>
235 auto parser = boost::make_shared<Subnets4ListConfigParser>(check_iface_);
236 return (parser);
237}
238
240 : check_iface_(check_iface) {
241}
242
245 bool encapsulate_options) {
246 SharedNetwork6Ptr shared_network;
247 std::string name;
248 try {
249 // Check parameters.
251 shared_network_data);
252
253 // Make sure that the network name has been specified. The name is required
254 // to create a SharedNetwork6 object.
255 std::string name = getString(shared_network_data, "name");
256 shared_network.reset(new SharedNetwork6(name));
257
258 // Move from reservation mode to new reservations flags.
259 ElementPtr mutable_params;
260 mutable_params = boost::const_pointer_cast<Element>(shared_network_data);
262
263 // Parse parameters common to all Network derivations.
264 NetworkPtr network = boost::dynamic_pointer_cast<Network>(shared_network);
265 parseCommon(mutable_params, network);
266
267 // preferred-lifetime
268 shared_network->setPreferred(parseIntTriplet(shared_network_data,
269 "preferred-lifetime"));
270
271 // Get interface-id option content. For now we support string
272 // representation only
273 Optional<std::string> ifaceid;
274 if (shared_network_data->contains("interface-id")) {
275 ifaceid = getString(shared_network_data, "interface-id");
276 }
277
278 // Interface is an optional parameter
280 if (shared_network_data->contains("interface")) {
281 iface = getString(shared_network_data, "interface");
282 }
283
284 // Specifying both interface for locally reachable subnets and
285 // interface id for relays is mutually exclusive. Need to test for
286 // this condition.
287 if (!ifaceid.unspecified() && !iface.unspecified() && !ifaceid.empty() &&
288 !iface.empty()) {
290 "parser error: interface (defined for locally reachable "
291 "subnets) and interface-id (defined for subnets reachable"
292 " via relays) cannot be defined at the same time for "
293 "shared network " << name << "("
294 << shared_network_data->getPosition() << ")");
295 }
296
297 // Configure interface-id for remote interfaces, if defined
298 if (!ifaceid.unspecified() && !ifaceid.empty()) {
299 std::string ifaceid_value = ifaceid.get();
300 OptionBuffer tmp(ifaceid_value.begin(), ifaceid_value.end());
302 shared_network->setInterfaceId(opt);
303 }
304
305 // Set interface name. If it is defined, then subnets are available
306 // directly over specified network interface.
307 if (!iface.unspecified() && !iface.empty()) {
308 if (check_iface_ && !IfaceMgr::instance().getIface(iface)) {
309 ConstElementPtr error = shared_network_data->get("interface");
311 "Specified network interface name " << iface
312 << " for shared network " << name
313 << " is not present in the system ("
314 << error->getPosition() << ")");
315 }
316 shared_network->setIface(iface);
317 }
318
319 if (shared_network_data->contains("rapid-commit")) {
320 shared_network->setRapidCommit(getBoolean(shared_network_data,
321 "rapid-commit"));
322 }
323
324 if (shared_network_data->contains("option-data")) {
325 auto json = shared_network_data->get("option-data");
326 // Create parser instance for option-data.
327 CfgOptionPtr cfg_option = shared_network->getCfgOption();
328 auto parser = createOptionDataListParser();
329 parser->parse(cfg_option, json, encapsulate_options);
330 }
331
332 if (shared_network_data->contains("client-class")) {
333 std::string client_class = getString(shared_network_data, "client-class");
334 if (!client_class.empty()) {
335 shared_network->allowClientClass(client_class);
336 }
337 }
338
339 ConstElementPtr user_context = shared_network_data->get("user-context");
340 if (user_context) {
341 shared_network->setContext(user_context);
342 }
343
344 if (shared_network_data->contains("require-client-classes")) {
345 const std::vector<data::ElementPtr>& class_list =
346 shared_network_data->get("require-client-classes")->listValue();
347 for (auto cclass = class_list.cbegin();
348 cclass != class_list.cend(); ++cclass) {
349 if (((*cclass)->getType() != Element::string) ||
350 (*cclass)->stringValue().empty()) {
351 isc_throw(DhcpConfigError, "invalid class name ("
352 << (*cclass)->getPosition() << ")");
353 }
354 shared_network->requireClientClass((*cclass)->stringValue());
355 }
356 }
357
358 if (shared_network_data->contains("subnet6")) {
359 auto json = shared_network_data->get("subnet6");
360
361 // Create parser instance of subnet6.
362 auto parser = createSubnetsListParser();
363 Subnet6Collection subnets;
364 parser->parse(subnets, json);
365
366 // Add all returned subnets into shared network.
367 for (auto subnet = subnets.cbegin(); subnet != subnets.cend();
368 ++subnet) {
369 shared_network->add(*subnet);
370 }
371 }
372
373 if (shared_network_data->contains("relay")) {
374 auto relay_parms = shared_network_data->get("relay");
375 if (relay_parms) {
378 parser.parse(relay_info, relay_parms);
379 shared_network->setRelayInfo(*relay_info);
380 }
381 }
382
383 parseTeePercents(shared_network_data, network);
384
385 // Parse DDNS parameters
386 parseDdnsParams(shared_network_data, network);
387
388 // Parse lease cache parameters
389 parseCacheParams(shared_network_data, network);
390
391 // Parse allocator params.
392 parseAllocatorParams(shared_network_data, network);
393 if (network->getAllocatorType() == "flq") {
394 isc_throw(BadValue, "Free Lease Queue allocator is not supported for IPv6 address pools");
395 }
396
397 // Parse prefix delegation allocator params.
398 auto network6 = boost::dynamic_pointer_cast<Network6>(shared_network);
399 parsePdAllocatorParams(shared_network_data, network6);
400
401 } catch (const std::exception& ex) {
402 isc_throw(DhcpConfigError, ex.what() << " ("
403 << shared_network_data->getPosition() << ")");
404 }
405
406 // In order to take advantage of the dynamic inheritance of global
407 // parameters to a shared network we need to set a callback function
408 // for each shared network which can be used to fetch global parameters.
409 shared_network->setFetchGlobalsFn([]() -> ConstCfgGlobalsPtr {
410 return (CfgMgr::instance().getCurrentCfg()->getConfiguredGlobals());
411 });
412
413 return (shared_network);
414}
415
416boost::shared_ptr<OptionDataListParser>
418 auto parser = boost::make_shared<OptionDataListParser>(AF_INET6);
419 return (parser);
420}
421
422boost::shared_ptr<Subnets6ListConfigParser>
424 auto parser = boost::make_shared<Subnets6ListConfigParser>(check_iface_);
425 return (parser);
426}
427
428} // end of namespace isc::dhcp
429} // end of namespace isc
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
static void checkKeywords(const SimpleKeywords &keywords, isc::data::ConstElementPtr scope)
Checks acceptable keywords with their expected type.
static std::string getString(isc::data::ConstElementPtr scope, const std::string &name)
Returns a string parameter from a scope.
const isc::util::Triplet< uint32_t > parseIntTriplet(const data::ConstElementPtr &scope, const std::string &name)
Parses an integer triplet.
static bool getBoolean(isc::data::ConstElementPtr scope, const std::string &name)
Returns a boolean parameter from a scope.
void parseCacheParams(const data::ConstElementPtr &network_data, NetworkPtr &network)
Parses parameters related to lease cache settings.
void parseAllocatorParams(const data::ConstElementPtr &network_data, NetworkPtr &network)
Parses parameters pertaining to allocator selection.
void parseDdnsParams(const data::ConstElementPtr &network_data, NetworkPtr &network)
Parses parameters pertaining to DDNS behavior.
void parseCommon(const data::ConstElementPtr &network_data, NetworkPtr &network)
Parses common parameters.
static void moveReservationMode(isc::data::ElementPtr config)
Moves deprecated reservation-mode parameter to new reservations flags.
void parseTeePercents(const data::ConstElementPtr &network_data, NetworkPtr &network)
Parses parameters related to "percent" timers settings.
void parsePdAllocatorParams(const data::ConstElementPtr &network_data, Network6Ptr &network)
Parses parameters pertaining to prefix delegation allocator selection.
void parseOfferLft(const data::ConstElementPtr &network_data, Network4Ptr &network)
Parses offer-lifetime parameter (v4 only)
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition: cfgmgr.cc:25
To be removed. Please use ConfigError instead.
static IfaceMgr & instance()
IfaceMgr is a singleton class.
Definition: iface_mgr.cc:54
Holds optional information about relay.
Definition: network.h:162
boost::shared_ptr< Network::RelayInfo > RelayInfoPtr
Pointer to the RelayInfo structure.
Definition: network.h:210
static const size_t MAX_SNAME_LEN
length of the SNAME field in DHCPv4 message
Definition: pkt4.h:44
static const size_t MAX_FILE_LEN
length of the FILE field in DHCPv4 message
Definition: pkt4.h:47
parser for additional relay information
Definition: dhcp_parsers.h:449
void parse(const isc::dhcp::Network::RelayInfoPtr &relay_info, isc::data::ConstElementPtr relay_elem)
parses the actual relay parameters
virtual boost::shared_ptr< Subnets4ListConfigParser > createSubnetsListParser() const
Returns an instance of the Subnets4ListConfigParser to be used for parsing the subnets within the sha...
SharedNetwork4Parser(bool check_iface=true)
Constructor.
virtual boost::shared_ptr< OptionDataListParser > createOptionDataListParser() const
Returns an instance of the OptionDataListParser to be used in parsing the option-data structure.
bool check_iface_
Check if the specified interface exists in the system.
SharedNetwork4Ptr parse(const data::ConstElementPtr &shared_network_data, bool encapsulate_options=true)
Parses shared configuration information for IPv4 shared network.
Shared network holding IPv4 subnets.
SharedNetwork6Parser(bool check_iface=true)
Constructor.
virtual boost::shared_ptr< Subnets6ListConfigParser > createSubnetsListParser() const
Returns an instance of the Subnets6ListConfigParser to be used for parsing the subnets within the sha...
bool check_iface_
Check if the specified interface exists in the system.
virtual boost::shared_ptr< OptionDataListParser > createOptionDataListParser() const
Returns an instance of the OptionDataListParser to be used in parsing the option-data structure.
SharedNetwork6Ptr parse(const data::ConstElementPtr &shared_network_data, bool encapsulate_options=true)
Parses shared configuration information for IPv6 shared network.
Shared network holding IPv6 subnets.
static const isc::data::SimpleKeywords SHARED_NETWORK4_PARAMETERS
This table defines all shared network parameters for DHCPv4.
static const isc::data::SimpleKeywords SHARED_NETWORK6_PARAMETERS
This table defines all shared network parameters for DHCPv6.
T get() const
Retrieves the encapsulated value.
Definition: optional.h:114
bool empty() const
Checks if the encapsulated value is empty.
Definition: optional.h:153
void unspecified(bool unspecified)
Modifies the flag that indicates whether the value is specified or unspecified.
Definition: optional.h:136
@ D6O_INTERFACE_ID
Definition: dhcp6.h:38
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:29
boost::shared_ptr< Element > ElementPtr
Definition: data.h:28
@ error
Definition: db_log.h:116
boost::shared_ptr< const CfgGlobals > ConstCfgGlobalsPtr
Const shared pointer to a CfgGlobals instance.
Definition: cfg_globals.h:163
boost::shared_ptr< Network4 > Network4Ptr
Pointer to the Network4 object.
Definition: network.h:1413
boost::shared_ptr< CfgOption > CfgOptionPtr
Non-const pointer.
Definition: cfg_option.h:803
boost::multi_index_container< Subnet6Ptr, boost::multi_index::indexed_by< boost::multi_index::ordered_unique< boost::multi_index::tag< SubnetSubnetIdIndexTag >, boost::multi_index::const_mem_fun< Subnet, SubnetID, &Subnet::getID > >, boost::multi_index::ordered_unique< boost::multi_index::tag< SubnetPrefixIndexTag >, boost::multi_index::const_mem_fun< Subnet, std::string, &Subnet::toText > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SubnetModificationTimeIndexTag >, boost::multi_index::const_mem_fun< data::BaseStampedElement, boost::posix_time::ptime, &data::BaseStampedElement::getModificationTime > > > > Subnet6Collection
A collection of Subnet6 objects.
Definition: subnet.h:974
boost::shared_ptr< SharedNetwork6 > SharedNetwork6Ptr
Pointer to SharedNetwork6 object.
boost::multi_index_container< Subnet4Ptr, boost::multi_index::indexed_by< boost::multi_index::ordered_unique< boost::multi_index::tag< SubnetSubnetIdIndexTag >, boost::multi_index::const_mem_fun< Subnet, SubnetID, &Subnet::getID > >, boost::multi_index::ordered_unique< boost::multi_index::tag< SubnetPrefixIndexTag >, boost::multi_index::const_mem_fun< Subnet, std::string, &Subnet::toText > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SubnetServerIdIndexTag >, boost::multi_index::const_mem_fun< Network4, asiolink::IOAddress, &Network4::getServerId > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< SubnetModificationTimeIndexTag >, boost::multi_index::const_mem_fun< data::BaseStampedElement, boost::posix_time::ptime, &data::BaseStampedElement::getModificationTime > > > > Subnet4Collection
A collection of Subnet4 objects.
Definition: subnet.h:903
boost::shared_ptr< Network > NetworkPtr
Pointer to the Network object.
Definition: network.h:73
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Definition: option.h:24
boost::shared_ptr< SharedNetwork4 > SharedNetwork4Ptr
Pointer to SharedNetwork4 object.
boost::shared_ptr< Option > OptionPtr
Definition: option.h:37
Definition: edns.h:19
Defines the logger used by the top-level component of kea-lfc.