Kea 3.3.4
cb_parsers.cc
Go to the documentation of this file.
1// Copyright (C) 2026 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 <dhcp/dhcp4.h>
11#include <dhcp/libdhcp++.h>
12#include <dhcp/option_space.h>
18#include <dhcpsrv/subnet.h>
19
20#include <cstdint>
21#include <iomanip>
22#include <utility>
23
24#include <boost/make_shared.hpp>
25
26#include <cb_cmds/cb_parsers.h>
27
28using namespace std;
29using namespace isc::asiolink;
30using namespace isc::db;
31using namespace isc::data;
32using namespace isc::dhcp;
33using namespace isc::util;
34
35namespace isc {
36namespace cb {
37
38string
40 if (global_parameter->getType() != Element::string) {
41 isc_throw(BadValue, "parameter name must be a string");
42 }
43
44 auto name = global_parameter->stringValue();
45
46 if (name.empty()) {
47 isc_throw(BadValue, "'name' parameter must not be empty");
48 }
49 if (!keywords_.count(name)) {
50 isc_throw(BadValue, "unknown parameter '" << name << "'");
51 }
52
53 return (name);
54}
55
58 StampedValueCollection parsed_globals;
59
60 for (auto const& name_value_pair : global_parameter_data->mapValue()) {
61 auto name = name_value_pair.first;
62 if (name.empty()) {
63 isc_throw(BadValue, "name of the global parameter must not be empty");
64 }
65 auto kit = keywords_.find(name);
66 if (kit == keywords_.end()) {
67 isc_throw(BadValue, "unknown parameter '" << name << "'");
68 }
69
70 auto parameter_value = name_value_pair.second;
71 if (parameter_value->getType() != kit->second) {
72 isc_throw(BadValue, "bad parameter '" << name << "' value type: "
73 << "expected " << Element::typeToName(kit->second) << ", got "
74 << Element::typeToName(parameter_value->getType()));
75 }
76 if (parameter_value->getType() == Element::map) {
77 for (auto const& sub_name_value_pair : parameter_value->mapValue()) {
78 auto sub_name = sub_name_value_pair.first;
79 if (sub_name.empty()) {
80 isc_throw(BadValue, "name of the global parameter must not be empty");
81 }
82 std::string full_name = name + "." + sub_name;
83 auto kitf = keywords_.find(full_name);
84 if (kitf == keywords_.end()) {
85 isc_throw(BadValue, "unknown parameter '" << name << "." << sub_name << "'");
86 }
87
88 auto sub_parameter_value = sub_name_value_pair.second;
89 if (sub_parameter_value->getType() != kitf->second) {
90 isc_throw(BadValue, "bad parameter '" << name << "." << sub_name << "' value type: "
91 << "expected " << Element::typeToName(kitf->second) << ", got "
92 << Element::typeToName(sub_parameter_value->getType()));
93 }
94 StampedValuePtr stamped_value(new StampedValue(full_name,
95 copy(sub_parameter_value, 0)));
96 parsed_globals.insert(stamped_value);
97 }
98 } else if (parameter_value->getType() == Element::list) {
99 for (size_t i = 0; i < parameter_value->size(); ++i) {
100 auto const sub_type = parameter_value->get(i)->getType();
101 auto sub_kit = list_keywords_.find(name);
102 if (sub_kit == list_keywords_.end()) {
103 isc_throw(BadValue, "unknown list parameter subtype '" << name << "'");
104 }
105 if (sub_type != sub_kit->second) {
106 isc_throw(BadValue, "bad list parameter '" << name << "' value type: "
107 << "expected " << Element::typeToName(sub_kit->second) << ", got "
108 << Element::typeToName(sub_type));
109 }
110 }
111 StampedValuePtr stamped_value(new StampedValue(name, parameter_value->str()));
112 parsed_globals.insert(stamped_value);
113 } else {
114 StampedValuePtr stamped_value(new StampedValue(name,
115 copy(parameter_value, 0)));
116 parsed_globals.insert(stamped_value);
117 }
118 }
119
120 return (parsed_globals);
121}
122
125 // Get mutable version of option definition element.
126 ElementPtr mutable_option_def =
127 boost::const_pointer_cast<Element>(option_def);
128
129 // Apply defaults.
130 SimpleParser::setDefaults(mutable_option_def,
131 (address_family_ == AF_INET ?
134
135 // Call the option definition parser.
136 OptionDefParser parser(address_family_);
137 OptionDefinitionPtr def = parser.parse(option_def);
138
139 // Check that the option definition does not conflict with
140 // a standard option definition.
141 if (LibDHCP::getOptionDef(def->getOptionSpaceName(), def->getCode())) {
142 isc_throw(BadValue, "an option with code " << def->getCode()
143 << " already exists in space '"
144 << def->getOptionSpaceName() << "'");
145 } else if (LibDHCP::getOptionDef(def->getOptionSpaceName(),
146 def->getName())) {
147 isc_throw(BadValue, "an option with name '" << def->getName()
148 << "' already exists in space '"
149 << def->getOptionSpaceName() << "'");
150 }
151
152 return (def);
153}
154
156CBOptionPairParser::OPTION_REQUIRED = { "code" };
157
159CBOptionPairParser::OPTION_KEYWORDS = {
160 { "code", Element::integer },
161 { "space", Element::string }
162};
163
164pair<uint16_t, string>
165CBOptionPairParser::parse(ConstElementPtr option, bool skip_keywords /* = false */) {
166 checkRequired(OPTION_REQUIRED, option);
167 if (!skip_keywords) {
168 checkKeywords(OPTION_KEYWORDS, option);
169 }
170 string space = address_family_ == AF_INET ?
172 ConstElementPtr elem = option->get("space");
173 if (elem) {
174 if (!OptionSpace::validateName(elem->stringValue())) {
175 isc_throw(BadValue, "'space' parameter must be a valid space name");
176 }
177 space = elem->stringValue();
178 }
179
180 int64_t code = getInteger(option, "code");
181 int64_t max_code;
182 if (address_family_ == AF_INET) {
183 max_code = numeric_limits<uint8_t>::max();
184 } else {
185 max_code = numeric_limits<uint16_t>::max();
186 }
187 if ((code < 0) || (code > max_code)) {
188 isc_throw(OutOfRange, "invalid 'code' value not in [0.."
189 << max_code << "]");
190 }
191
192 if (space == DHCP4_OPTION_SPACE) {
193 if (code == DHO_PAD) {
194 isc_throw(OutOfRange, "invalid 'code' value 0: reserved for PAD");
195 } else if (code == DHO_END) {
196 isc_throw(OutOfRange, "invalid 'code' value 255: reserved for END");
197 }
198 } else if (space == DHCP6_OPTION_SPACE) {
199 if (code == 0) {
200 isc_throw(OutOfRange, "invalid 'code' value 0: reserved");
201 }
202 }
203
204 return (make_pair(static_cast<uint16_t>(code), space));
205}
206
209 static SimpleKeywords keywords = {
210 { "code", Element::integer },
211 { "space", Element::string },
212 { "force", Element::boolean }
213 };
214
215 checkKeywords(keywords, option_def);
216
217 ConstElementPtr elem = option_def->get("force");
218 bool force = false;
219 if (elem) {
220 try {
221 force = elem->boolValue();
222 } catch (const Exception& ex) {
223 isc_throw(BadValue, "Invalid 'force' must be a boolean value: " << elem);
224 }
225 }
226
227 auto opt_pair = CBOptionPairParser::parse(option_def, true);
228 return (make_tuple(opt_pair.first, opt_pair.second, force));
229}
230
233 static SimpleKeywords keywords = {
234 { "code", Element::integer },
235 { "space", Element::string },
236 { "client-classes", Element::list }
237 };
238
239 checkKeywords(keywords, option);
240
241 ConstElementPtr elem = option->get("client-classes");
242 ClientClassesPtr cclasses;
243 if (elem) {
244 cclasses.reset(new ClientClasses());
245 cclasses->fromElement(elem);
246 }
247
248 auto opt_pair = CBOptionPairParser::parse(option, true);
249 return (make_tuple(opt_pair.first, opt_pair.second, cclasses));
250}
251
252CBOptionDataParser::CBOptionDataParser(const uint16_t address_family,
253 CfgOptionDefPtr cfg_option_def,
254 BackendSelector& backend_selector,
255 ServerSelector& server_selector)
256 : OptionDataParser(address_family, cfg_option_def),
257 backend_selector_(backend_selector),
258 server_selector_(server_selector) {
259}
260
262CBOptionDataParser::findOptionDefinition(const std::string& option_space,
263 const Optional<uint32_t>& option_code,
264 const Optional<std::string>& option_name) const {
266 if (option_code.unspecified() && option_name.unspecified()) {
267 return (def);
268 }
269
270 // Class specific option definitions take precedence.
271 if (cfg_option_def_) {
272 if (option_code.unspecified()) {
273 def = cfg_option_def_->get(option_space, option_name);
274 } else {
275 def = cfg_option_def_->get(option_space, option_code);
276 }
277 }
278
279 if (!def) {
280 // Check if this is a standard option.
281 if (option_code.unspecified()) {
282 def = LibDHCP::getOptionDef(option_space, option_name);
283 } else {
284 def = LibDHCP::getOptionDef(option_space, option_code);
285 }
286 }
287
288 if (!def) {
289 // Check if this is a vendor-option. If it is, get vendor-specific
290 // definition.
291 uint32_t vendor_id = LibDHCP::optionSpaceToVendorId(option_space);
292 if (vendor_id) {
293 const Option::Universe u = address_family_ == AF_INET ?
295 if (option_code.unspecified()) {
296 def = LibDHCP::getVendorOptionDef(u, vendor_id, option_name);
297 } else {
298 def = LibDHCP::getVendorOptionDef(u, vendor_id, option_code);
299 }
300 }
301 }
302
303 if (!def) {
304 // Check if the option has been defined in the config backend.
305 OptionDefContainerPtr cb_defs;
306 if (address_family_ == AF_INET) {
307 cb_defs = boost::make_shared<OptionDefContainer>
308 (ConfigBackendDHCPv4Mgr::instance().getPool()->getAllOptionDefs4(backend_selector_,
310 } else {
311 cb_defs = boost::make_shared<OptionDefContainer>
312 (ConfigBackendDHCPv6Mgr::instance().getPool()->getAllOptionDefs6(backend_selector_,
314 }
315
316 if (!cb_defs->empty()) {
317 if (option_code.unspecified()) {
318 const OptionDefContainerNameIndex& idx = cb_defs->get<2>();
319 const OptionDefContainerNameRange& range = idx.equal_range(option_name);
320 if (std::distance(range.first, range.second) > 0) {
321 def = *range.first;
322 }
323 } else {
324 const OptionDefContainerTypeIndex& idx = cb_defs->get<1>();
325 const OptionDefContainerTypeRange& range = idx.equal_range(option_code);
326 if (std::distance(range.first, range.second) > 0) {
327 def = *range.first;
328 }
329 }
330 }
331 }
332
333 // The definition was not found in the config backend. It can be present in our
334 // configuration file. For example, this server can be used to manage the
335 // configurations for multiple instances and have option definitions defined
336 // in the configuration file.
337 if (!def) {
338 if (option_code.unspecified()) {
339 def = LibDHCP::getRuntimeOptionDef(option_space, option_name);
340 } else {
341 def = LibDHCP::getRuntimeOptionDef(option_space, option_code);
342 }
343 }
344
345 if (!def) {
346 if (option_code.unspecified()) {
347 def = LibDHCP::getLastResortOptionDef(option_space, option_name);
348 } else {
349 def = LibDHCP::getLastResortOptionDef(option_space, option_code);
350 }
351 }
352
353 return (def);
354}
355
357 CfgOptionDefPtr cfg_option_def,
358 BackendSelector& backend_selector,
359 ServerSelector& server_selector)
360 : OptionDataListParser(address_family, cfg_option_def),
361 backend_selector_(backend_selector),
362 server_selector_(server_selector) {
363}
364
365boost::shared_ptr<OptionDataParser>
367 auto parser = boost::make_shared<CBOptionDataParser>(address_family_, cfg_option_def_,
369 return (parser);
370}
371
373CBPoolRangeParser::POOL_REQUIRED = { "pool" };
374
376CBPoolRangeParser::POOL_KEYWORDS = {
377 { "pool", Element::string }
378};
379
380std::pair<IOAddress, IOAddress>
382 checkRequired(POOL_REQUIRED, pool);
383 checkKeywords(POOL_KEYWORDS, pool);
384 PoolStoragePtr pools(new PoolStorage());
385 if (address_family_ == AF_INET) {
386 Pool4Parser parser;
387 parser.parse(pools, pool, address_family_);
388 } else {
389 Pool6Parser parser;
390 parser.parse(pools, pool, address_family_);
391 }
392 if (pools->size() != 1) {
393 isc_throw(Unexpected, "parser does not return one pool");
394 }
395 return (make_pair(pools->at(0)->getFirstAddress(),
396 pools->at(0)->getLastAddress()));
397}
398
400 ServerSelector& server_selector)
401 : PdPoolParser(), backend_selector_(backend_selector),
402 server_selector_(server_selector) {
403}
404
405boost::shared_ptr<OptionDataListParser>
407 auto parser = boost::make_shared<CBOptionDataListParser>(AF_INET6,
411 return (parser);
412}
413
415 ServerSelector& server_selector)
416 : PdPoolsListParser(), backend_selector_(backend_selector),
417 server_selector_(server_selector) {
418}
419
420boost::shared_ptr<PdPoolParser>
422 auto parser = boost::make_shared<CBPdPoolParser>(backend_selector_,
424 return (parser);
425}
426
428CBPdPoolPrefixParser::PD_POOL_REQUIRED = { "prefix", "prefix-len" };
429
431CBPdPoolPrefixParser::PD_POOL_KEYWORDS = {
432 { "prefix", Element::string },
433 { "prefix-len", Element::integer }
434};
435
436std::pair<IOAddress, uint8_t>
438 checkRequired(PD_POOL_REQUIRED, pd_pool);
439 checkKeywords(PD_POOL_KEYWORDS, pd_pool);
440
441 string addr_str = getString(pd_pool, "prefix");
442 int64_t len = getInteger(pd_pool, "prefix-len");
443
444 if ((len <= 0) || (len > 128)) {
446 "'prefix-len' value must be in range of [1..128]");
447 }
449 try {
450 addr = IOAddress(addr_str);
451 } catch (const std::exception& ex) {
452 isc_throw(BadValue, "invalid 'prefix': " << ex.what());
453 }
454 if (!addr.isV6()) {
455 isc_throw(BadValue, "'prefix' value is not a valid IPv6 prefix");
456 }
457 if (len != 128) {
458 IOAddress first_address = firstAddrInPrefix(addr, len);
459 if (first_address != addr) {
460 isc_throw(BadValue, "Invalid Pool6 address boundaries: " << addr
461 << " is not the first address in prefix: " << first_address
462 << "/" << static_cast<uint32_t>(len));
463 }
464 }
465 return (std::make_pair(addr, static_cast<uint8_t>(len)));
466}
467
469CBSubnetIdParser::SUBNET_ID_REQUIRED = { "id" };
470
472CBSubnetIdParser::SUBNET_ID_KEYWORDS = {
473 { "id", Element::integer }
474};
475
478 checkRequired(SUBNET_ID_REQUIRED, subnet);
479 checkKeywords(SUBNET_ID_KEYWORDS, subnet);
480 int64_t id = getInteger(subnet, "id");
481 if ((id <= 0) || (id > static_cast<int64_t>(SUBNET_ID_MAX))) {
482 isc_throw(OutOfRange, "'id' parameter must be in [1.."
483 << SUBNET_ID_MAX << "] range");
484 }
485 return (static_cast<SubnetID>(id));
486}
487
489CBSubnetPrefixParser::SUBNET_PREFIX_REQUIRED = { "subnet" };
490
492CBSubnetPrefixParser::SUBNET_PREFIX_KEYWORDS = {
493 { "subnet", Element::string }
494};
495
496string
498 checkRequired(SUBNET_PREFIX_REQUIRED, subnet);
499 checkKeywords(SUBNET_PREFIX_KEYWORDS, subnet);
500 string prefix = getString(subnet, "subnet");
501 if (prefix.empty()) {
502 isc_throw(BadValue, "'subnet' parameter must not be empty");
503 }
504 if (address_family_ == AF_INET) {
505 static_cast<void>(Subnet4::parsePrefix(prefix));
506 } else {
507 static_cast<void>(Subnet6::parsePrefix(prefix));
508 }
509
510 // Check against spurious id (0 can be added as default).
511 ConstElementPtr id = subnet->get("id");
512 if (id && (id->intValue() != 0)) {
513 isc_throw(BadValue, "spurious 'id' parameter");
514 }
515 return (prefix);
516}
517
519 ServerSelector& server_selector)
520 : Subnet4ConfigParser(false), backend_selector_(backend_selector),
521 server_selector_(server_selector) {
522}
523
526
527 // Subnet identifier is mandatory.
528 data::ConstElementPtr id = subnet->get("id");
529 if (!id) {
530 isc_throw(BadValue, "subnet 'id' is mandatory for the remote-subnet4-set command");
531 }
532 if (id->getType() != Element::integer) {
533 isc_throw(BadValue, "'id' is not an integer");
534 }
535 int64_t idv = id->intValue();
536 int64_t idmax = SUBNET_ID_MAX;
537 if ((idv <= 0) || (idv > idmax)) {
538 isc_throw(OutOfRange, "'id' parameter must be in [1.."
539 << idmax << "] range");
540 }
541
542 ConstElementPtr hosts = subnet->get("reservations");
543 if (hosts) {
544 // Reject not a list.
545 if (hosts->getType() != Element::list) {
546 isc_throw(BadValue, "'reservations' entry is not a list");
547 }
548 // Reject not empty.
549 if (!hosts->empty()) {
550 isc_throw(BadValue, "'reservations' entry is not empty. This "
551 "is not supported by the remote-subnet4-set command");
552 }
553 }
554
555 // Call the parent class method on a copy without the shared network name.
556 ElementPtr copy = data::copy(subnet);
557 if (copy->contains("shared-network-name")) {
558 copy->remove("shared-network-name");
559 }
560 auto result = Subnet4ConfigParser::parse(copy, false);
561
562 // Check if the subnet should be associated with a shared network.
563 auto shared_network_name_element = subnet->get("shared-network-name");
564 if (shared_network_name_element) {
565 std::string shared_network_name;
566
567 // Shared network name must be a string or null.
568 if (shared_network_name_element->getType() == Element::string) {
569 shared_network_name = shared_network_name_element->stringValue();
570
571 } else if ((shared_network_name_element->getType() != Element::null)) {
572 isc_throw(BadValue, "'shared-network-name' must be a string or null");
573 }
574
575 // Associate the subnet with shared network or disassociate if the
576 // shared network name is empty or null.
577 result->setSharedNetworkName(shared_network_name);
578
579 } else {
580 isc_throw(BadValue, "'shared-network-name' is mandatory (but can"
581 " be null or empty)");
582 }
583
584 return (result);
585}
586
587boost::shared_ptr<OptionDataListParser>
589 auto parser = boost::make_shared<CBOptionDataListParser>(AF_INET,
593 return (parser);
594}
595
596boost::shared_ptr<dhcp::PoolsListParser>
598 auto parser = boost::make_shared<CBPools4ListParser>(backend_selector_,
600 return (parser);
601}
602
604 ServerSelector& server_selector)
605 : Subnet6ConfigParser(false), backend_selector_(backend_selector),
606 server_selector_(server_selector) {
607}
608
611
612 // Subnet identifier is mandatory.
613 ConstElementPtr id = subnet->get("id");
614 if (!id) {
615 isc_throw(BadValue, "subnet 'id' is mandatory for the remote-subnet6-set command");
616 }
617 if (id->getType() != Element::integer) {
618 isc_throw(BadValue, "'id' is not an integer");
619 }
620 int64_t idv = id->intValue();
621 int64_t idmax = dhcp::SUBNET_ID_MAX;
622 if ((idv <= 0) || (idv > idmax)) {
623 isc_throw(OutOfRange, "'id' parameter must be in [1.."
624 << idmax << "] range");
625 }
626
627 ConstElementPtr hosts = subnet->get("reservations");
628 if (hosts) {
629 // Reject not a list.
630 if (hosts->getType() != Element::list) {
631 isc_throw(BadValue, "'reservations' entry is not a list");
632 }
633 // Reject not empty.
634 if (!hosts->empty()) {
635 isc_throw(BadValue, "'reservations' entry is not empty. This "
636 "is not supported by the remote-subnet6-set command");
637 }
638 }
639
640 // Call the parent class method on a copy without the shared network name.
641 ElementPtr copy = data::copy(subnet);
642 if (copy->contains("shared-network-name")) {
643 copy->remove("shared-network-name");
644 }
645 auto result = Subnet6ConfigParser::parse(copy, false);
646
647 // Check if the subnet should be associated with a shared network.
648 auto shared_network_name_element = subnet->get("shared-network-name");
649 if (shared_network_name_element) {
650 std::string shared_network_name;
651
652 // Shared network name must be a string or null.
653 if (shared_network_name_element->getType() == Element::string) {
654 shared_network_name = shared_network_name_element->stringValue();
655
656 } else if ((shared_network_name_element->getType() != Element::null)) {
657 isc_throw(BadValue, "'shared-network-name' must be a string or null");
658 }
659
660 // Associate the subnet with shared network or disassociate if the
661 // shared network name is empty or null.
662 result->setSharedNetworkName(shared_network_name);
663
664 } else {
665 isc_throw(BadValue, "'shared-network-name' is mandatory (but can"
666 " be null or empty)");
667 }
668
669 return (result);
670}
671
672boost::shared_ptr<OptionDataListParser>
674 auto parser = boost::make_shared<CBOptionDataListParser>(AF_INET6,
678 return (parser);
679}
680
681boost::shared_ptr<PoolsListParser>
683 auto parser = boost::make_shared<CBPools6ListParser>(backend_selector_,
685 return (parser);
686}
687
688boost::shared_ptr<PdPoolsListParser>
690 auto parser = boost::make_shared<CBPdPoolsListParser>(backend_selector_,
692 return (parser);
693}
694
696 ServerSelector& server_selector)
697 : Subnets4ListConfigParser(false), backend_selector_(backend_selector),
698 server_selector_(server_selector) {
699}
700
701boost::shared_ptr<Subnet4ConfigParser>
703 auto parser = boost::make_shared<CBSubnet4ConfigParser>(backend_selector_, server_selector_);
704 return (parser);
705}
706
708 ServerSelector& server_selector)
709 : Subnets6ListConfigParser(false), backend_selector_(backend_selector),
710 server_selector_(server_selector) {
711}
712
713boost::shared_ptr<Subnet6ConfigParser>
715 auto parser = boost::make_shared<CBSubnet6ConfigParser>(backend_selector_, server_selector_);
716 return (parser);
717}
718
720CBSharedNetworkNameParser::SHARED_NETWORK_REQUIRED = { "name" };
721
723CBSharedNetworkNameParser::SHARED_NETWORK_KEYWORDS = {
724 { "name", Element::string }
725};
726
727string
729 checkRequired(SHARED_NETWORK_REQUIRED, shared_network);
730 checkKeywords(SHARED_NETWORK_KEYWORDS, shared_network);
731 string name = getString(shared_network, "name");
732 if (name.empty()) {
733 isc_throw(BadValue, "'name' parameter must not be empty");
734 }
735 return (name);
736}
737
739 ServerSelector& server_selector)
740 : SharedNetwork4Parser(false), backend_selector_(backend_selector),
741 server_selector_(server_selector) {
742}
743
746 // Subnets must not be updated via remote-network4-set command.
747 // Throw an error if the subnet4 list is included.
748 ConstElementPtr subnets = shared_network->get("subnet4");
749 if (subnets) {
751 "'subnet4' must not be specified for the shared network. "
752 "Use 'remote-subnet4-set command to add a subnet to the "
753 "shared network");
754 }
755
756 // Call the parent class method.
757 SharedNetwork4Ptr net = SharedNetwork4Parser::parse(shared_network, false);
758
759 if (!net) {
760 // Should not happen because on errors it throws...
761 isc_throw(Unexpected, "SharedNetwork4Parser::parse returns null?!");
762 }
763
764 // Last, let's check name of the shared network.
765 if (net->getName().empty()) {
766 isc_throw(BadValue, "'name' parameter must not be empty");
767 }
768
769 return (net);
770}
771
772boost::shared_ptr<OptionDataListParser>
774 auto parser = boost::make_shared<CBOptionDataListParser>(AF_INET,
778 return (parser);
779}
780
781boost::shared_ptr<Subnets4ListConfigParser>
783 auto parser = boost::make_shared<CBSubnets4ListConfigParser>(backend_selector_,
785 return (parser);
786}
787
789 ServerSelector& server_selector)
790 : SharedNetwork6Parser(false), backend_selector_(backend_selector),
791 server_selector_(server_selector) {
792}
793
796 // Subnets must not be updated via remote-network6-set command.
797 // Throw an error if the subnet6 list is included.
798 ConstElementPtr subnets = shared_network->get("subnet6");
799 if (subnets) {
801 "'subnet6' must not be specified for the shared network. "
802 "Use 'remote-subnet6-set command to add a subnet to the "
803 "shared network");
804 }
805
806 // Call the parent class method.
807 SharedNetwork6Ptr net = SharedNetwork6Parser::parse(shared_network, false);
808
809 if (!net) {
810 // Should not happen because on errors it throws...
811 isc_throw(Unexpected, "SharedNetwork6Parser::parse returns null?!");
812 }
813
814 // Last, let's check name of the shared network.
815 if (net->getName().empty()) {
816 isc_throw(BadValue, "'name' parameter must not be empty");
817 }
818
819 return (net);
820}
821
822boost::shared_ptr<OptionDataListParser>
824 auto parser = boost::make_shared<CBOptionDataListParser>(AF_INET6,
828 return (parser);
829}
830
831boost::shared_ptr<Subnets6ListConfigParser>
833 auto parser = boost::make_shared<CBSubnets6ListConfigParser>(backend_selector_,
835 return (parser);
836}
837
839 ServerSelector& server_selector)
840 : backend_selector_(backend_selector), server_selector_(server_selector) {
841}
842
843boost::shared_ptr<OptionDataListParser>
845 CfgOptionDefPtr cfg_option_def) const {
846 auto parser = boost::make_shared<CBOptionDataListParser>(address_family,
847 cfg_option_def,
850 return (parser);
851}
852
854 CfgOptionDefPtr cfg_option_def,
855 BackendSelector& backend_selector,
856 ServerSelector& server_selector)
857 : family_(family), cfg_option_def_(cfg_option_def), backend_selector_(backend_selector),
858 server_selector_(server_selector) {
859}
860
861std::pair<ClientClassDefPtr, std::string>
863 ClientClassDictionaryPtr class_dict = boost::make_shared<ClientClassDictionary>();
864 CBClientClassDefParser parser(backend_selector_, server_selector_);
865 // Parse with skipping dependency checks. Such checks should be conducted
866 // at the database level.
867 parser.parse(class_dict, client_class, family_, true, false);
868
869 if (client_class->get("template-test")) {
870 isc_throw(BadValue, "template classes are not supported");
871 }
872
873 std::string follow_class_name = "";
874 if (client_class->contains("follow-class-name")) {
875 // This parameter may be null if the caller is not interested in placing
876 // an inserted client class into any specific position or the updated
877 // class's position should not change.
878 if (client_class->get("follow-class-name")->getType() != Element::null) {
879 // Otherwise, it should be string.
880 follow_class_name = getString(client_class, "follow-class-name");
881 }
882 }
883 ClientClassDefPtr parsed_client_class;
884 if (!class_dict->getClasses()->empty()) {
885 parsed_client_class = *(class_dict->getClasses()->begin());
886 }
887 return (std::make_pair(parsed_client_class, follow_class_name));
888}
889
891CBClientClassNameParser::CLIENT_CLASS_REQUIRED = { "name" };
892
894CBClientClassNameParser::CLIENT_CLASS_KEYWORDS = {
895 { "name", Element::string }
896};
897
898string
900 checkRequired(CLIENT_CLASS_REQUIRED, client_class);
901 checkKeywords(CLIENT_CLASS_KEYWORDS, client_class);
902 string name = getString(client_class, "name");
903 if (name.empty()) {
904 isc_throw(BadValue, "'name' parameter must not be empty");
905 }
906 return (name);
907}
908
910ServerTagParser::SERVER_TAG_REQUIRED = { "server-tag" };
911
913ServerTagParser::SERVER_TAG_KEYWORDS = {
914 { "server-tag", Element::string }
915};
916
917ServerTag
919 checkRequired(SERVER_TAG_REQUIRED, server);
920 checkKeywords(SERVER_TAG_KEYWORDS, server);
921 string tag = getString(server, "server-tag");
922 return (ServerTag(tag));
923}
924
926ServerConfigParser::SERVER_CONFIG_REQUIRED = { "server-tag" };
927
929ServerConfigParser::SERVER_CONFIG_KEYWORDS = {
930 { "server-tag", Element::string },
931 { "description", Element::string }
932};
933
936 checkRequired(SERVER_CONFIG_REQUIRED, server);
937 checkKeywords(SERVER_CONFIG_KEYWORDS, server);
938 string tag = getString(server, "server-tag");
939 ConstElementPtr desc = server->get("description");
940 if (desc) {
941 return (db::Server::create(ServerTag(tag), desc->stringValue()));
942 } else {
943 return (db::Server::create(ServerTag(tag)));
944 }
945}
946
947} // end of namespace cb
948} // end of namespace isc
Parsers for a subset of an object specification, e.g.
static std::string typeToName(Element::types type)
Returns the name of the given type as a string.
Definition data.cc:716
@ map
Definition data.h:160
@ null
Definition data.h:156
@ integer
Definition data.h:153
@ boolean
Definition data.h:155
@ list
Definition data.h:159
@ string
Definition data.h:157
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
This is a base class for exceptions thrown from the DNS library module.
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
A generic exception that is thrown when an unexpected error condition occurs.
Overrides the default parser for DHCP client classes.
Definition cb_parsers.h:938
virtual boost::shared_ptr< OptionDataListParser > createOptionDataListParser(const uint16_t address_family, CfgOptionDefPtr cfg_option_def) const
Returns an instance of the CBOptionDataListParser.
db::BackendSelector & backend_selector_
Backend selector used to fetch option definitions during option data parsing.
Definition cb_parsers.h:964
CBClientClassDefParser(db::BackendSelector &backend_selector, db::ServerSelector &server_selector)
Constructor.
db::ServerSelector & server_selector_
Server selector used to fetch option definitions during option data parsing.
Definition cb_parsers.h:968
std::string parse(data::ConstElementPtr client_class)
Parses a client class name.
CBClientClassParser(uint16_t family, CfgOptionDefPtr cfg_option_def, db::BackendSelector &backend_selector, db::ServerSelector &server_selector)
Constructor.
std::pair< dhcp::ClientClassDefPtr, std::string > parse(data::ConstElementPtr client_class)
Parses a client class.
virtual boost::shared_ptr< OptionDataParser > createOptionDataParser() const
Returns an instance of the CBOptionDataListParser to be used in parsing options.
CBOptionDataListParser(const uint16_t address_family, CfgOptionDefPtr cfg_option_def, db::BackendSelector &backend_selector, db::ServerSelector &server_selector)
Constructor.
db::BackendSelector & backend_selector_
Backend selector used to fetch option definitions during option data parsing.
Definition cb_parsers.h:333
db::ServerSelector & server_selector_
Server selector used to fetch option definitions during option data parsing.
Definition cb_parsers.h:337
virtual dhcp::OptionDefinitionPtr findOptionDefinition(const std::string &option_space, const util::Optional< uint32_t > &option_code, const util::Optional< std::string > &option_name) const
Finds an option definition within an option space.
db::BackendSelector & backend_selector_
Backend selector to be used to fetch option definitions during option data parsing.
Definition cb_parsers.h:294
db::ServerSelector & server_selector_
Server selector to be used to fetch option definitions during option data parsing.
Definition cb_parsers.h:298
CBOptionDataParser(const uint16_t address_family, dhcp::CfgOptionDefPtr cfg_option_def, db::BackendSelector &backend_selector, db::ServerSelector &server_selector)
Constructor.
CBOptionDefDelete parse(data::ConstElementPtr option)
Parses an option into code + space pair.
dhcp::OptionDefinitionPtr parse(data::ConstElementPtr option_def)
Parses an option definition.
std::pair< uint16_t, std::string > parse(data::ConstElementPtr option, bool skip_keywords=false)
Parses an option into code + space pair.
CBOptionTuple parse(data::ConstElementPtr option)
Parses an option into code + space pair.
CBPdPoolParser(db::BackendSelector &backend_selector, db::ServerSelector &server_selector)
Constructor.
virtual boost::shared_ptr< OptionDataListParser > createOptionDataListParser() const
Returns an instance of the CBOptionDataListParser to be used in parsing the option-data structure.
db::ServerSelector & server_selector_
Server selector used to fetch option definitions during option data parsing.
Definition cb_parsers.h:510
db::BackendSelector & backend_selector_
Backend selector used to fetch option definitions during option data parsing.
Definition cb_parsers.h:506
std::pair< asiolink::IOAddress, uint8_t > parse(data::ConstElementPtr pd_pool)
Parses a prefix delegation pool prefix.
virtual boost::shared_ptr< PdPoolParser > createPdPoolConfigParser() const
Returns an instance of the CBPdPoolParser to be used in parsing the prefix delegation pools.
db::BackendSelector & backend_selector_
Backend selector used to fetch option definitions during option data parsing.
Definition cb_parsers.h:538
CBPdPoolsListParser(db::BackendSelector &backend_selector, db::ServerSelector &server_selector)
Constructor.
db::ServerSelector & server_selector_
Server selector used to fetch option definitions during option data parsing.
Definition cb_parsers.h:542
std::pair< asiolink::IOAddress, asiolink::IOAddress > parse(data::ConstElementPtr pool)
Parses an address pool range.
db::ServerSelector & server_selector_
Server selector used to fetch option definitions during option data parsing.
Definition cb_parsers.h:885
CBSharedNetwork4Parser(db::BackendSelector &backend_selector, db::ServerSelector &server_selector)
Constructor.
db::BackendSelector & backend_selector_
Backend selector used to fetch option definitions during option data parsing.
Definition cb_parsers.h:881
dhcp::SharedNetwork4Ptr parse(data::ConstElementPtr shared_network)
Parses a single IPv4 shared network configuration.
virtual boost::shared_ptr< OptionDataListParser > createOptionDataListParser() const
Returns an instance of the CBOptionDataListParser to be used in parsing the option-data structure.
virtual boost::shared_ptr< Subnets4ListConfigParser > createSubnetsListParser() const
Returns an instance of the CBSubnets4ListConfigParser to be used for parsing the subnets within the s...
db::BackendSelector & backend_selector_
Backend selector used to fetch option definitions during option data parsing.
Definition cb_parsers.h:928
virtual boost::shared_ptr< OptionDataListParser > createOptionDataListParser() const
Returns an instance of the CBOptionDataListParser to be used in parsing the option-data structure.
db::ServerSelector & server_selector_
Server selector used to fetch option definitions during option data parsing.
Definition cb_parsers.h:932
CBSharedNetwork6Parser(db::BackendSelector &backend_selector, db::ServerSelector &server_selector)
Constructor.
dhcp::SharedNetwork6Ptr parse(data::ConstElementPtr shared_network)
Parses a single IPv6 shared network configuration.
virtual boost::shared_ptr< Subnets6ListConfigParser > createSubnetsListParser() const
Returns an instance of the CBSubnets6ListConfigParser to be used for parsing the subnets within the s...
std::string parse(data::ConstElementPtr shared_network)
Parses a shared network name.
dhcp::Subnet4Ptr parse(data::ConstElementPtr subnet)
Parses a single subnet configuration.
db::BackendSelector & backend_selector_
Backend selector used for fetching option definitions during option data parsing.
Definition cb_parsers.h:676
virtual boost::shared_ptr< OptionDataListParser > createOptionDataListParser() const
Returns an instance of the CBOptionDataListParser to be used in parsing the option-data structure.
virtual boost::shared_ptr< dhcp::PoolsListParser > createPoolsListParser() const
Returns an instance of the CBPools4ListParser.
db::ServerSelector & server_selector_
Server selector used for fetching option definitions during option data parsing.
Definition cb_parsers.h:680
CBSubnet4ConfigParser(db::BackendSelector &backend_selector, db::ServerSelector &server_selector)
Constructor.
dhcp::Subnet6Ptr parse(data::ConstElementPtr subnet)
Parses a single subnet configuration.
virtual boost::shared_ptr< OptionDataListParser > createOptionDataListParser() const
Returns an instance of the CBOptionDataListParser to be used in parsing the option-data structure.
virtual boost::shared_ptr< dhcp::PoolsListParser > createPoolsListParser() const
Returns an instance of the CBPools6ListParser.
CBSubnet6ConfigParser(db::BackendSelector &backend_selector, db::ServerSelector &server_selector)
Constructor.
db::ServerSelector & server_selector_
Server selector used for fetching option definitions during option data parsing.
Definition cb_parsers.h:739
db::BackendSelector & backend_selector_
Backend selector used for fetching option definitions during option data parsing.
Definition cb_parsers.h:735
virtual boost::shared_ptr< dhcp::PdPoolsListParser > createPdPoolsListParser() const
Returns an instance of the CBPdPoolsListParser.
dhcp::SubnetID parse(data::ConstElementPtr subnet)
Parses a subnet id.
std::string parse(data::ConstElementPtr subnet)
Parses a subnet prefix.
db::BackendSelector & backend_selector_
Backend selector used to fetch option definitions during option data parsing.
Definition cb_parsers.h:769
CBSubnets4ListConfigParser(db::BackendSelector &backend_selector, db::ServerSelector &server_selector)
Constructor.
db::ServerSelector & server_selector_
Server selector used to fetch option definitions during option data parsing.
Definition cb_parsers.h:773
virtual boost::shared_ptr< Subnet4ConfigParser > createSubnetConfigParser() const
Returns an instance of the CBSubnet4ConfigParser to be used in parsing the subnets.
db::ServerSelector & server_selector_
Server selector used to fetch option definitions during option data parsing.
Definition cb_parsers.h:807
db::BackendSelector & backend_selector_
Backend selector used to fetch option definitions during option data parsing.
Definition cb_parsers.h:803
virtual boost::shared_ptr< Subnet6ConfigParser > createSubnetConfigParser() const
Returns an instance of the CBSubnet6ConfigParser to be used in parsing the subnets.
CBSubnets6ListConfigParser(db::BackendSelector &backend_selector, db::ServerSelector &server_selector)
Constructor.
std::string parse(data::ConstElementPtr global_parameter)
Parses global parameter name.
Definition cb_parsers.cc:39
data::StampedValueCollection parse(const data::ConstElementPtr &global_parameter_data)
Parses global parameters information.
Definition cb_parsers.cc:57
db::ServerPtr parse(data::ConstElementPtr server)
Parses a single server configuration.
data::ServerTag parse(data::ConstElementPtr server)
Parses server tag.
Represents a server tag.
Definition server_tag.h:25
static void checkKeywords(const SimpleKeywords &keywords, isc::data::ConstElementPtr scope)
Checks acceptable keywords with their expected type.
static void checkRequired(const SimpleRequiredKeywords &required, isc::data::ConstElementPtr scope)
Checks that all required keywords are present.
static std::string getString(isc::data::ConstElementPtr scope, const std::string &name)
Returns a string parameter from a scope.
static int64_t getInteger(isc::data::ConstElementPtr scope, const std::string &name)
Returns an integer parameter from a scope.
static size_t setDefaults(isc::data::ElementPtr scope, const SimpleDefaults &default_values)
Sets the default values.
This class represents a named configuration parameter, e.g.
Config Backend selector.
Server selector for associating objects in a database with specific servers.
static ServerPtr create(const data::ServerTag &tag, const std::string &description="")
Factory function to be used to create an instance of the Server object.
Definition server.cc:29
void parse(ClientClassDictionaryPtr &class_dictionary, isc::data::ConstElementPtr client_class_def, uint16_t family, bool append_error_position=true, bool check_dependencies=true)
Parses an entry that describes single client class definition.
Container for storing client class names.
Definition classify.h:111
static ConfigBackendDHCPv4Mgr & instance()
Returns a sole instance of the ConfigBackendDHCPv4Mgr.
static ConfigBackendDHCPv6Mgr & instance()
Returns a sole instance of the ConfigBackendDHCPv6Mgr.
static OptionDefinitionPtr getOptionDef(const std::string &space, const uint16_t code)
Return the first option definition matching a particular option code.
Definition libdhcp++.cc:132
static OptionDefinitionPtr getVendorOptionDef(const Option::Universe u, const uint32_t vendor_id, const uint16_t code)
Returns vendor option definition for a given vendor-id and code.
Definition libdhcp++.cc:174
static uint32_t optionSpaceToVendorId(const std::string &option_space)
Converts option space name to vendor id.
static OptionDefinitionPtr getRuntimeOptionDef(const std::string &space, const uint16_t code)
Returns runtime (non-standard) option definition by space and option code.
Definition libdhcp++.cc:195
static OptionDefinitionPtr getLastResortOptionDef(const std::string &space, const uint16_t code)
Returns last resort option definition by space and option code.
Definition libdhcp++.cc:253
CfgOptionDefPtr cfg_option_def_
Config option definitions.
OptionDataListParser(const uint16_t address_family, CfgOptionDefPtr cfg_option_def=CfgOptionDefPtr())
Constructor.
uint16_t address_family_
Address family: AF_INET or AF_INET6.
uint16_t address_family_
Address family: AF_INET or AF_INET6.
CfgOptionDefPtr cfg_option_def_
Config option definitions.
OptionDataParser(const uint16_t address_family, CfgOptionDefPtr cfg_option_def=CfgOptionDefPtr())
Constructor.
Parser for a single option definition.
OptionDefinitionPtr parse(isc::data::ConstElementPtr option_def)
Parses an entry that describes single option definition.
static bool validateName(const std::string &name)
Checks that the provided option space name is valid.
Universe
defines option universe DHCPv4 or DHCPv6
Definition option.h:91
Parser for a list of prefix delegation pools.
Parser for IPv4 pool definitions.
Parser for IPv6 pool definitions.
virtual void parse(PoolStoragePtr pools, isc::data::ConstElementPtr pool_structure, const uint16_t address_family, bool encapsulate_options=true)
parses the actual structure
SharedNetwork4Parser(bool check_iface=true)
Constructor.
SharedNetwork4Ptr parse(const data::ConstElementPtr &shared_network_data, bool encapsulate_options=true)
Parses shared configuration information for IPv4 shared network.
SharedNetwork6Parser(bool check_iface=true)
Constructor.
SharedNetwork6Ptr parse(const data::ConstElementPtr &shared_network_data, bool encapsulate_options=true)
Parses shared configuration information for IPv6 shared network.
static const isc::data::SimpleDefaults OPTION4_DEF_DEFAULTS
This table defines default values for option definitions in DHCPv4.
static const isc::data::SimpleDefaults OPTION6_DEF_DEFAULTS
This table defines default values for option definitions in DHCPv6.
Subnet4ConfigParser(bool check_iface=true)
Constructor.
Subnet4Ptr parse(data::ConstElementPtr subnet, bool encapsulate_options=true)
Parses a single IPv4 subnet configuration and adds to the Configuration Manager.
static std::pair< asiolink::IOAddress, uint8_t > parsePrefix(const std::string &prefix)
Converts subnet prefix to a pair of prefix/length pair.
Definition subnet.cc:809
Subnet6Ptr parse(data::ConstElementPtr subnet, bool encapsulate_options=true)
Parses a single IPv6 subnet configuration and adds to the Configuration Manager.
Subnet6ConfigParser(bool check_iface=true)
Constructor.
static std::pair< asiolink::IOAddress, uint8_t > parsePrefix(const std::string &prefix)
Converts subnet prefix to a pair of prefix/length pair.
Definition subnet.cc:924
Subnets4ListConfigParser(bool check_iface=true)
constructor
Subnets6ListConfigParser(bool check_iface=true)
constructor
A template representing an optional value.
Definition optional.h:37
void unspecified(bool unspecified)
Modifies the flag that indicates whether the value is specified or unspecified.
Definition optional.h:145
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
std::tuple< uint16_t, std::string, ClientClassesPtr > CBOptionTuple
Defines a tuple for the three values that may be used as a key for an option.
Definition cb_parsers.h:168
std::tuple< uint16_t, std::string, bool > CBOptionDefDelete
Defines a tuple of values for deleting an option definition: the option code, option space,...
Definition cb_parsers.h:165
boost::shared_ptr< StampedValue > StampedValuePtr
Pointer to the stamped value.
std::vector< std::string > SimpleRequiredKeywords
This specifies all required keywords.
boost::multi_index_container< StampedValuePtr, boost::multi_index::indexed_by< boost::multi_index::hashed_non_unique< boost::multi_index::tag< StampedValueNameIndexTag >, boost::multi_index::const_mem_fun< StampedValue, std::string, &StampedValue::getName > >, boost::multi_index::ordered_non_unique< boost::multi_index::tag< StampedValueModificationTimeIndexTag >, boost::multi_index::const_mem_fun< BaseStampedElement, boost::posix_time::ptime, &BaseStampedElement::getModificationTime > > > > StampedValueCollection
Multi index container for StampedValue.
ElementPtr copy(ConstElementPtr from, unsigned level)
Copy the data up to a nesting level.
Definition data.cc:1543
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:30
boost::shared_ptr< Element > ElementPtr
Definition data.h:29
std::map< std::string, isc::data::Element::types > SimpleKeywords
This specifies all accepted keywords with their types.
boost::shared_ptr< Server > ServerPtr
Shared pointer to the Server class.
Definition server.h:22
boost::shared_ptr< Subnet4 > Subnet4Ptr
A pointer to a Subnet4 object.
Definition subnet.h:458
std::vector< PoolPtr > PoolStorage
a collection of pools
@ DHO_END
Definition dhcp4.h:229
@ DHO_PAD
Definition dhcp4.h:69
boost::shared_ptr< CfgOptionDef > CfgOptionDefPtr
Non-const pointer.
boost::shared_ptr< Subnet6 > Subnet6Ptr
A pointer to a Subnet6 object.
Definition subnet.h:623
boost::shared_ptr< ClientClasses > ClientClassesPtr
Smart pointer to ClientClasses object.
Definition classify.h:304
boost::shared_ptr< ClientClassDef > ClientClassDefPtr
a pointer to an ClientClassDef
boost::shared_ptr< OptionDefinition > OptionDefinitionPtr
Pointer to option definition object.
boost::shared_ptr< SharedNetwork6 > SharedNetwork6Ptr
Pointer to SharedNetwork6 object.
boost::shared_ptr< PoolStorage > PoolStoragePtr
boost::shared_ptr< ClientClassDictionary > ClientClassDictionaryPtr
Defines a pointer to a ClientClassDictionary.
std::pair< OptionDefContainerNameIndex::const_iterator, OptionDefContainerNameIndex::const_iterator > OptionDefContainerNameRange
Pair of iterators to represent the range of options definitions having the same option name.
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition subnet_id.h:25
OptionDefContainer::nth_index< 2 >::type OptionDefContainerNameIndex
Type of the index #2 - option name.
std::pair< OptionDefContainerTypeIndex::const_iterator, OptionDefContainerTypeIndex::const_iterator > OptionDefContainerTypeRange
Pair of iterators to represent the range of options definitions having the same option type value.
boost::shared_ptr< SharedNetwork4 > SharedNetwork4Ptr
Pointer to SharedNetwork4 object.
OptionDefContainer::nth_index< 1 >::type OptionDefContainerTypeIndex
Type of the index #1 - option type.
boost::shared_ptr< OptionDefContainer > OptionDefContainerPtr
Pointer to an option definition container.
Defines the logger used by the top-level component of kea-lfc.
#define DHCP4_OPTION_SPACE
global std option spaces
#define DHCP6_OPTION_SPACE