Kea 1.5.0
dhcp_parsers.cc
Go to the documentation of this file.
1// Copyright (C) 2013-2018 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 // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include <config.h>
5#include <dhcp/iface_mgr.h>
6#include <dhcp/libdhcp++.h>
7#include <dhcpsrv/cfgmgr.h>
15#include <util/encode/hex.h>
16#include <util/strutil.h>
17
18#include <boost/algorithm/string.hpp>
19#include <boost/foreach.hpp>
20#include <boost/lexical_cast.hpp>
21#include <boost/scoped_ptr.hpp>
22
23#include <map>
24#include <string>
25#include <vector>
26
27using namespace std;
28using namespace isc::asiolink;
29using namespace isc::data;
30using namespace isc::util;
31
32namespace isc {
33namespace dhcp {
34
35// ******************** MACSourcesListConfigParser *************************
36
37void
39 CfgIface cfg_iface;
40 uint32_t source = 0;
41 size_t cnt = 0;
42
43 // By default, there's only one source defined: ANY.
44 // If user specified anything, we need to get rid of that default.
45 mac_sources.clear();
46
47 BOOST_FOREACH(ConstElementPtr source_elem, value->listValue()) {
48 std::string source_str = source_elem->stringValue();
49 try {
50 source = CfgMACSource::MACSourceFromText(source_str);
51 mac_sources.add(source);
52 ++cnt;
53 } catch (const InvalidParameter& ex) {
54 isc_throw(DhcpConfigError, "The mac-sources value '" << source_str
55 << "' was specified twice (" << value->getPosition() << ")");
56 } catch (const std::exception& ex) {
57 isc_throw(DhcpConfigError, "Failed to convert '"
58 << source_str << "' to any recognized MAC source:"
59 << ex.what() << " (" << value->getPosition() << ")");
60 }
61 }
62
63 if (!cnt) {
64 isc_throw(DhcpConfigError, "If specified, MAC Sources cannot be empty");
65 }
66}
67
68// ******************** ControlSocketParser *************************
70 if (!value) {
71 // Sanity check: not supposed to fail.
72 isc_throw(DhcpConfigError, "Logic error: specified control-socket is null");
73 }
74
75 if (value->getType() != Element::map) {
76 // Sanity check: not supposed to fail.
77 isc_throw(DhcpConfigError, "Specified control-socket is expected to be a map"
78 ", i.e. a structure defined within { }");
79 }
80 srv_cfg.setControlSocketInfo(value);
81}
82
83template<typename SearchKey>
85OptionDataParser::findOptionDefinition(const std::string& option_space,
86 const SearchKey& search_key) const {
87 OptionDefinitionPtr def = LibDHCP::getOptionDef(option_space, search_key);
88
89 if (!def) {
90 // Check if this is a vendor-option. If it is, get vendor-specific
91 // definition.
92 uint32_t vendor_id = LibDHCP::optionSpaceToVendorId(option_space);
93 if (vendor_id) {
94 const Option::Universe u = address_family_ == AF_INET ?
96 def = LibDHCP::getVendorOptionDef(u, vendor_id, search_key);
97 }
98 }
99
100 if (!def) {
101 // Check if this is an option specified by a user.
102 def = CfgMgr::instance().getStagingCfg()->getCfgOptionDef()
103 ->get(option_space, search_key);
104 }
105
106 return (def);
107}
108
109// ******************************** OptionDefParser ****************************
110
111std::pair<isc::dhcp::OptionDefinitionPtr, std::string>
113
114 // Get mandatory parameters.
115 std::string name = getString(option_def, "name");
116 uint32_t code = getInteger(option_def, "code");
117 std::string type = getString(option_def, "type");
118
119 // Get optional parameters. Whoever called this parser, should have
120 // called SimpleParser::setDefaults first.
121 bool array_type = getBoolean(option_def, "array");
122 std::string record_types = getString(option_def, "record-types");
123 std::string space = getString(option_def, "space");
124 std::string encapsulates = getString(option_def, "encapsulate");
125 ConstElementPtr user_context = option_def->get("user-context");
126
127 if (!OptionSpace::validateName(space)) {
128 isc_throw(DhcpConfigError, "invalid option space name '"
129 << space << "' ("
130 << getPosition("space", option_def) << ")");
131 }
132
133 // Create option definition.
135 // We need to check if user has set encapsulated option space
136 // name. If so, different constructor will be used.
137 if (!encapsulates.empty()) {
138 // Arrays can't be used together with sub-options.
139 if (array_type) {
140 isc_throw(DhcpConfigError, "option '" << space << "."
141 << "name" << "', comprising an array of data"
142 << " fields may not encapsulate any option space ("
143 << option_def->getPosition() << ")");
144
145 } else if (encapsulates == space) {
146 isc_throw(DhcpConfigError, "option must not encapsulate"
147 << " an option space it belongs to: '"
148 << space << "." << name << "' is set to"
149 << " encapsulate '" << space << "' ("
150 << option_def->getPosition() << ")");
151
152 } else {
153 def.reset(new OptionDefinition(name, code, type,
154 encapsulates.c_str()));
155 }
156
157 } else {
158 def.reset(new OptionDefinition(name, code, type, array_type));
159
160 }
161
162 if (user_context) {
163 def->setContext(user_context);
164 }
165
166 // Split the list of record types into tokens.
167 std::vector<std::string> record_tokens =
168 isc::util::str::tokens(record_types, ",");
169 // Iterate over each token and add a record type into
170 // option definition.
171 BOOST_FOREACH(std::string record_type, record_tokens) {
172 try {
173 boost::trim(record_type);
174 if (!record_type.empty()) {
175 def->addRecordField(record_type);
176 }
177 } catch (const Exception& ex) {
178 isc_throw(DhcpConfigError, "invalid record type values"
179 << " specified for the option definition: "
180 << ex.what() << " ("
181 << getPosition("record-types", option_def) << ")");
182 }
183 }
184
185 // Validate the definition.
186 try {
187 def->validate();
188 } catch (const std::exception& ex) {
190 << " (" << option_def->getPosition() << ")");
191 }
192
193 // Option definition has been created successfully.
194 return make_pair(def, space);
195}
196
197// ******************************** OptionDefListParser ************************
198void
200 if (!option_def_list) {
201 // Sanity check: not supposed to fail.
202 isc_throw(DhcpConfigError, "parser error: a pointer to a list of"
203 << " option definitions is NULL ("
204 << option_def_list->getPosition() << ")");
205 }
206
207 OptionDefParser parser;
208 BOOST_FOREACH(ConstElementPtr option_def, option_def_list->listValue()) {
210
211 def = parser.parse(option_def);
212 try {
213 storage->add(def.first, def.second);
214 } catch (const std::exception& ex) {
215 // Append position if there is a failure.
216 isc_throw(DhcpConfigError, ex.what() << " ("
217 << option_def->getPosition() << ")");
218 }
219 }
220
221 // All definitions have been prepared. Put them as runtime options into
222 // the libdhcp++.
223 LibDHCP::setRuntimeOptionDefs(storage->getContainer());
224}
225
226//****************************** RelayInfoParser ********************************
228 : family_(family) {
229};
230
231void
233 ConstElementPtr relay_elem) {
234
235 if (relay_elem->getType() != Element::map) {
236 isc_throw(DhcpConfigError, "relay must be a map");
237 }
238
239 ConstElementPtr address = relay_elem->get("ip-address");
240 ConstElementPtr addresses = relay_elem->get("ip-addresses");
241
242 if (address && addresses) {
244 "specify either ip-address or ip-addresses, not both");
245 }
246
247 if (!address && !addresses) {
248 isc_throw(DhcpConfigError, "ip-addresses is required");
249 }
250
251 // Create our resultant RelayInfo structure
252 *relay_info = isc::dhcp::Network::RelayInfo();
253
254 if (address) {
255 addAddress("ip-address", getString(relay_elem, "ip-address"),
256 relay_elem, relay_info);
258 DHCPSRV_CFGMGR_RELAY_IP_ADDRESS_DEPRECATED)
259 .arg(getPosition("ip-address", relay_elem));
260 return;
261 }
262
263 if (addresses->getType() != Element::list) {
264 isc_throw(DhcpConfigError, "ip-addresses must be a list "
265 << " (" << getPosition("ip-addresses", relay_elem) << ")");
266 }
267
268 BOOST_FOREACH(ConstElementPtr address_element, addresses->listValue()) {
269 addAddress("ip-addresses", address_element->stringValue(),
270 relay_elem, relay_info);
271 }
272}
273
274void
275RelayInfoParser::addAddress(const std::string& name,
276 const std::string& address_str,
277 ConstElementPtr relay_elem,
278 const isc::dhcp::Network::RelayInfoPtr& relay_info) {
279 boost::scoped_ptr<isc::asiolink::IOAddress> ip;
280 try {
281 ip.reset(new isc::asiolink::IOAddress(address_str));
282 } catch (const std::exception& ex) {
283 isc_throw(DhcpConfigError, "address " << address_str
284 << " is not a valid: "
285 << (family_ == Option::V4 ? "IPv4" : "IPv6")
286 << "address"
287 << " (" << getPosition(name, relay_elem) << ")");
288 }
289
290 // Check if the address family matches.
291 if ((ip->isV4() && family_ != Option::V4) ||
292 (ip->isV6() && family_ != Option::V6) ) {
293 isc_throw(DhcpConfigError, "address " << address_str
294 << " is not a: "
295 << (family_ == Option::V4 ? "IPv4" : "IPv6")
296 << "address"
297 << " (" << getPosition(name, relay_elem) << ")");
298 }
299
300 try {
301 relay_info->addAddress(*ip);
302 } catch (const std::exception& ex) {
303 isc_throw(DhcpConfigError, "cannot add address: " << address_str
304 << "to relay info: " << ex.what()
305 << " (" << getPosition(name, relay_elem) << ")");
306 }
307}
308
309//****************************** PoolParser ********************************
310
311void
313 ConstElementPtr pool_structure,
314 const uint16_t address_family) {
315
316 ConstElementPtr text_pool = pool_structure->get("pool");
317
318 if (!text_pool) {
319 isc_throw(DhcpConfigError, "Mandatory 'pool' entry missing in "
320 "definition: (" << pool_structure->getPosition() << ")");
321 }
322
323 // That should be a single pool representation. It should contain
324 // text is form prefix/len or first - last. Note that spaces
325 // are allowed
326 string txt = text_pool->stringValue();
327
328 // first let's remove any whitespaces
329 boost::erase_all(txt, " "); // space
330 boost::erase_all(txt, "\t"); // tabulation
331
332 PoolPtr pool;
333
334 // Is this prefix/len notation?
335 size_t pos = txt.find("/");
336 if (pos != string::npos) {
337 isc::asiolink::IOAddress addr("::");
338 uint8_t len = 0;
339 try {
340 addr = isc::asiolink::IOAddress(txt.substr(0, pos));
341
342 // start with the first character after /
343 string prefix_len = txt.substr(pos + 1);
344
345 // It is lexical cast to int and then downcast to uint8_t.
346 // Direct cast to uint8_t (which is really an unsigned char)
347 // will result in interpreting the first digit as output
348 // value and throwing exception if length is written on two
349 // digits (because there are extra characters left over).
350
351 // No checks for values over 128. Range correctness will
352 // be checked in Pool4 constructor, here we only check
353 // the representation fits in an uint8_t as this can't
354 // be done by a direct lexical cast as explained...
355 int val_len = boost::lexical_cast<int>(prefix_len);
356 if ((val_len < std::numeric_limits<uint8_t>::min()) ||
357 (val_len > std::numeric_limits<uint8_t>::max())) {
358 // This exception will be handled 4 line later!
360 }
361 len = static_cast<uint8_t>(val_len);
362 } catch (...) {
363 isc_throw(DhcpConfigError, "Failed to parse pool "
364 "definition: " << txt << " ("
365 << text_pool->getPosition() << ")");
366 }
367
368 try {
369 pool = poolMaker(addr, len);
370 pools->push_back(pool);
371 } catch (const std::exception& ex) {
372 isc_throw(DhcpConfigError, "Failed to create pool defined by: "
373 << txt << " (" << text_pool->getPosition() << ")");
374 }
375
376 } else {
377 isc::asiolink::IOAddress min("::");
378 isc::asiolink::IOAddress max("::");
379
380 // Is this min-max notation?
381 pos = txt.find("-");
382 if (pos != string::npos) {
383 // using min-max notation
384 try {
385 min = isc::asiolink::IOAddress(txt.substr(0, pos));
386 max = isc::asiolink::IOAddress(txt.substr(pos + 1));
387 } catch (...) {
388 isc_throw(DhcpConfigError, "Failed to parse pool "
389 "definition: " << txt << " ("
390 << text_pool->getPosition() << ")");
391 }
392
393 try {
394 pool = poolMaker(min, max);
395 pools->push_back(pool);
396 } catch (const std::exception& ex) {
397 isc_throw(DhcpConfigError, "Failed to create pool defined by: "
398 << txt << " (" << text_pool->getPosition() << ")");
399 }
400 }
401 }
402
403 if (!pool) {
404 isc_throw(DhcpConfigError, "invalid pool definition: "
405 << text_pool->stringValue() <<
406 ". There are two acceptable formats <min address-max address>"
407 " or <prefix/len> ("
408 << text_pool->getPosition() << ")");
409 }
410
411 // If there's user-context specified, store it.
412 ConstElementPtr user_context = pool_structure->get("user-context");
413 if (user_context) {
414 // The grammar accepts only maps but still check it.
415 if (user_context->getType() != Element::map) {
416 isc_throw(isc::dhcp::DhcpConfigError, "User context has to be a map ("
417 << user_context->getPosition() << ")");
418 }
419 pool->setContext(user_context);
420 }
421
422 // Parser pool specific options.
423 ConstElementPtr option_data = pool_structure->get("option-data");
424 if (option_data) {
425 try {
426 CfgOptionPtr cfg = pool->getCfgOption();
427 OptionDataListParser option_parser(address_family);
428 option_parser.parse(cfg, option_data);
429 } catch (const std::exception& ex) {
431 << " (" << option_data->getPosition() << ")");
432 }
433 }
434
435 // Client-class.
436 ConstElementPtr client_class = pool_structure->get("client-class");
437 if (client_class) {
438 string cclass = client_class->stringValue();
439 if (!cclass.empty()) {
440 pool->allowClientClass(cclass);
441 }
442 }
443
444 // Try setting up required client classes.
445 ConstElementPtr class_list = pool_structure->get("require-client-classes");
446 if (class_list) {
447 const std::vector<data::ElementPtr>& classes = class_list->listValue();
448 for (auto cclass = classes.cbegin();
449 cclass != classes.cend(); ++cclass) {
450 if (((*cclass)->getType() != Element::string) ||
451 (*cclass)->stringValue().empty()) {
452 isc_throw(DhcpConfigError, "invalid class name ("
453 << (*cclass)->getPosition() << ")");
454 }
455 pool->requireClientClass((*cclass)->stringValue());
456 }
457 }
458}
459
460//****************************** Pool4Parser *************************
461
463Pool4Parser::poolMaker (IOAddress &addr, uint32_t len, int32_t) {
464 return (PoolPtr(new Pool4(addr, len)));
465}
466
469 return (PoolPtr(new Pool4(min, max)));
470}
471
472//****************************** Pool4ListParser *************************
473
474void
476 BOOST_FOREACH(ConstElementPtr pool, pools_list->listValue()) {
477 Pool4Parser parser;
478 parser.parse(pools, pool, AF_INET);
479 }
480}
481
482//****************************** SubnetConfigParser *************************
483
485 : pools_(new PoolStorage()),
486 address_family_(family),
487 options_(new CfgOption()) {
489}
490
493
494 ConstElementPtr options_params = subnet->get("option-data");
495 if (options_params) {
497 opt_parser.parse(options_, options_params);
498 }
499
500 ConstElementPtr relay_params = subnet->get("relay");
501 if (relay_params) {
503 RelayInfoParser parser(u);
504 parser.parse(relay_info_, relay_params);
505 }
506
507 // Create a subnet.
508 try {
509 createSubnet(subnet);
510 } catch (const std::exception& ex) {
512 "subnet configuration failed: " << ex.what());
513 }
514
515 return (subnet_);
516}
517
519SubnetConfigParser::hrModeFromText(const std::string& txt) {
520 if ( (txt.compare("disabled") == 0) ||
521 (txt.compare("off") == 0) ) {
522 return (Network::HR_DISABLED);
523 } else if (txt.compare("out-of-pool") == 0) {
525 } else if (txt.compare("global") == 0) {
526 return (Network::HR_GLOBAL);
527 } else if (txt.compare("all") == 0) {
528 return (Network::HR_ALL);
529 } else {
530 // Should never happen...
531 isc_throw(BadValue, "Can't convert '" << txt
532 << "' into any valid reservation-mode values");
533 }
534}
535
536void
537SubnetConfigParser::createSubnet(ConstElementPtr params) {
538 std::string subnet_txt;
539 try {
540 subnet_txt = getString(params, "subnet");
541 } catch (const DhcpConfigError &) {
542 // rethrow with precise error
543 isc_throw(DhcpConfigError,
544 "mandatory 'subnet' parameter is missing for a subnet being"
545 " configured (" << params->getPosition() << ")");
546 }
547
548 // Remove any spaces or tabs.
549 boost::erase_all(subnet_txt, " ");
550 boost::erase_all(subnet_txt, "\t");
551
552 // The subnet format is prefix/len. We are going to extract
553 // the prefix portion of a subnet string to create IOAddress
554 // object from it. IOAddress will be passed to the Subnet's
555 // constructor later on. In order to extract the prefix we
556 // need to get all characters preceding "/".
557 size_t pos = subnet_txt.find("/");
558 if (pos == string::npos) {
559 ConstElementPtr elem = params->get("subnet");
560 isc_throw(DhcpConfigError,
561 "Invalid subnet syntax (prefix/len expected):" << subnet_txt
562 << " (" << elem->getPosition() << ")");
563 }
564
565 // Try to create the address object. It also validates that
566 // the address syntax is ok.
567 isc::asiolink::IOAddress addr(subnet_txt.substr(0, pos));
568
569 // Now parse out the prefix length.
570 unsigned int len;
571 try {
572 len = boost::lexical_cast<unsigned int>(subnet_txt.substr(pos + 1));
573 } catch (const boost::bad_lexical_cast&) {
574 ConstElementPtr elem = params->get("subnet");
575 isc_throw(DhcpConfigError, "prefix length: '" <<
576 subnet_txt.substr(pos+1) << "' is not an integer ("
577 << elem->getPosition() << ")");
578 }
579
580 // Sanity check the prefix length
581 if ((addr.isV6() && len > 128) ||
582 (addr.isV4() && len > 32)) {
583 ConstElementPtr elem = params->get("subnet");
585 "Invalid prefix length specified for subnet: " << len
586 << " (" << elem->getPosition() << ")");
587 }
588
589 // Call the subclass's method to instantiate the subnet
590 initSubnet(params, addr, len);
591
592 // Add pools to it.
593 for (PoolStorage::iterator it = pools_->begin(); it != pools_->end();
594 ++it) {
595 try {
596 subnet_->addPool(*it);
597 } catch (const BadValue& ex) {
598 // addPool() can throw BadValue if the pool is overlapping or
599 // is out of bounds for the subnet.
600 isc_throw(DhcpConfigError,
601 ex.what() << " (" << params->getPosition() << ")");
602 }
603 }
604 // If there's user-context specified, store it.
605 ConstElementPtr user_context = params->get("user-context");
606 if (user_context) {
607 // The grammar accepts only maps but still check it.
608 if (user_context->getType() != Element::map) {
609 isc_throw(isc::dhcp::DhcpConfigError, "User context has to be a map ("
610 << user_context->getPosition() << ")");
611 }
612 subnet_->setContext(user_context);
613 }
614
615}
616
617//****************************** Subnet4ConfigParser *************************
618
620 :SubnetConfigParser(AF_INET) {
621}
622
626 ConstElementPtr pools = subnet->get("pools");
627 if (pools) {
628 Pools4ListParser parser;
629 parser.parse(pools_, pools);
630 }
631
632 SubnetPtr generic = SubnetConfigParser::parse(subnet);
633
634 if (!generic) {
635 // Sanity check: not supposed to fail.
637 "Failed to create an IPv4 subnet (" <<
638 subnet->getPosition() << ")");
639 }
640
641 Subnet4Ptr sn4ptr = boost::dynamic_pointer_cast<Subnet4>(subnet_);
642 if (!sn4ptr) {
643 // If we hit this, it is a programming error.
645 "Invalid Subnet4 cast in Subnet4ConfigParser::parse");
646 }
647
648 // Set relay information if it was parsed
649 if (relay_info_) {
650 sn4ptr->setRelayInfo(*relay_info_);
651 }
652
653 // Parse Host Reservations for this subnet if any.
654 ConstElementPtr reservations = subnet->get("reservations");
655 if (reservations) {
656 HostCollection hosts;
658 parser.parse(subnet_->getID(), reservations, hosts);
659 for (auto h = hosts.begin(); h != hosts.end(); ++h) {
660 CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(*h);
661 }
662 }
663
664 return (sn4ptr);
665}
666
667void
669 asiolink::IOAddress addr, uint8_t len) {
670 // The renew-timer and rebind-timer are optional. If not set, the
671 // option 58 and 59 will not be sent to a client. In this case the
672 // client should formulate default values based on the valid-lifetime.
674 if (params->contains("renew-timer")) {
675 t1 = getInteger(params, "renew-timer");
676 }
677
679 if (params->contains("rebind-timer")) {
680 t2 = getInteger(params, "rebind-timer");
681 }
682
683 // The valid-lifetime is mandatory. It may be specified for a
684 // particular subnet. If not, the global value should be present.
685 // If there is no global value, exception is thrown.
686 Triplet<uint32_t> valid = getInteger(params, "valid-lifetime");
687
688 // Subnet ID is optional. If it is not supplied the value of 0 is used,
689 // which means autogenerate. The value was inserted earlier by calling
690 // SimpleParser4::setAllDefaults.
691 SubnetID subnet_id = static_cast<SubnetID>(getInteger(params, "id"));
692
693 stringstream s;
694 s << addr << "/" << static_cast<int>(len) << " with params: ";
695 // t1 and t2 are optional may be not specified.
696 if (!t1.unspecified()) {
697 s << "t1=" << t1 << ", ";
698 }
699 if (!t2.unspecified()) {
700 s << "t2=" << t2 << ", ";
701 }
702 s <<"valid-lifetime=" << valid;
703
704 LOG_INFO(dhcpsrv_logger, DHCPSRV_CFGMGR_NEW_SUBNET4).arg(s.str());
705
706 Subnet4Ptr subnet4(new Subnet4(addr, len, t1, t2, valid, subnet_id));
707 subnet_ = subnet4;
708
709 // Set the match-client-id value for the subnet. It is always present.
710 // If not explicitly specified, the default value was filled in when
711 // SimpleParser4::setAllDefaults was called.
712 bool match_client_id = getBoolean(params, "match-client-id");
713 subnet4->setMatchClientId(match_client_id);
714
715 // Set the authoritative value for the subnet. It is always present.
716 // If not explicitly specified, the default value was filled in when
717 // SimpleParser4::setAllDefaults was called.
718 bool authoritative = getBoolean(params, "authoritative");
719 subnet4->setAuthoritative(authoritative);
720
721 // Set next-server. The default value is 0.0.0.0. Nevertheless, the
722 // user could have messed that up by specifying incorrect value.
723 // To avoid using 0.0.0.0, user can specify "".
724 string next_server;
725 try {
726 next_server = getString(params, "next-server");
727 if (!next_server.empty()) {
728 subnet4->setSiaddr(IOAddress(next_server));
729 }
730 } catch (...) {
731 ConstElementPtr next = params->get("next-server");
732 string pos;
733 if (next) {
734 pos = next->getPosition().str();
735 } else {
736 pos = params->getPosition().str();
737 }
738 isc_throw(DhcpConfigError, "invalid parameter next-server : "
739 << next_server << "(" << pos << ")");
740 }
741
742 // Set server-hostname.
743 std::string sname = getString(params, "server-hostname");
744 if (!sname.empty()) {
745 if (sname.length() >= Pkt4::MAX_SNAME_LEN) {
746 ConstElementPtr error = params->get("server-hostname");
747 isc_throw(DhcpConfigError, "server-hostname must be at most "
748 << Pkt4::MAX_SNAME_LEN - 1 << " bytes long, it is "
749 << sname.length() << " ("
750 << error->getPosition() << ")");
751 }
752 subnet4->setSname(sname);
753 }
754
755 // Set boot-file-name.
756 std::string filename =getString(params, "boot-file-name");
757 if (!filename.empty()) {
758 if (filename.length() > Pkt4::MAX_FILE_LEN) {
759 ConstElementPtr error = params->get("boot-file-name");
760 isc_throw(DhcpConfigError, "boot-file-name must be at most "
761 << Pkt4::MAX_FILE_LEN - 1 << " bytes long, it is "
762 << filename.length() << " ("
763 << error->getPosition() << ")");
764 }
765 subnet4->setFilename(filename);
766 }
767
768 // Get interface name. If it is defined, then the subnet is available
769 // directly over specified network interface.
770 std::string iface = getString(params, "interface");
771 if (!iface.empty()) {
772 if (!IfaceMgr::instance().getIface(iface)) {
773 ConstElementPtr error = params->get("interface");
774 isc_throw(DhcpConfigError, "Specified network interface name " << iface
775 << " for subnet " << subnet4->toText()
776 << " is not present in the system ("
777 << error->getPosition() << ")");
778 }
779
780 subnet4->setIface(iface);
781 }
782
783 // Let's set host reservation mode. If not specified, the default value of
784 // all will be used.
785 try {
786 std::string hr_mode = getString(params, "reservation-mode");
787 subnet4->setHostReservationMode(hrModeFromText(hr_mode));
788 } catch (const BadValue& ex) {
789 isc_throw(DhcpConfigError, "Failed to process specified value "
790 " of reservation-mode parameter: " << ex.what()
791 << "(" << getPosition("reservation-mode", params) << ")");
792 }
793
794 // Try setting up client class.
795 string client_class = getString(params, "client-class");
796 if (!client_class.empty()) {
797 subnet4->allowClientClass(client_class);
798 }
799
800 // Try setting up required client classes.
801 ConstElementPtr class_list = params->get("require-client-classes");
802 if (class_list) {
803 const std::vector<data::ElementPtr>& classes = class_list->listValue();
804 for (auto cclass = classes.cbegin();
805 cclass != classes.cend(); ++cclass) {
806 if (((*cclass)->getType() != Element::string) ||
807 (*cclass)->stringValue().empty()) {
808 isc_throw(DhcpConfigError, "invalid class name ("
809 << (*cclass)->getPosition() << ")");
810 }
811 subnet4->requireClientClass((*cclass)->stringValue());
812 }
813 }
814
815 // 4o6 specific parameter: 4o6-interface. If not explicitly specified,
816 // it will have the default value of "".
817 string iface4o6 = getString(params, "4o6-interface");
818 if (!iface4o6.empty()) {
819 subnet4->get4o6().setIface4o6(iface4o6);
820 subnet4->get4o6().enabled(true);
821 }
822
823 // 4o6 specific parameter: 4o6-subnet. If not explicitly specified, it
824 // will have the default value of "".
825 string subnet4o6 = getString(params, "4o6-subnet");
826 if (!subnet4o6.empty()) {
827 size_t slash = subnet4o6.find("/");
828 if (slash == std::string::npos) {
829 isc_throw(DhcpConfigError, "Missing / in the 4o6-subnet parameter:"
830 << subnet4o6 << ", expected format: prefix6/length");
831 }
832 string prefix = subnet4o6.substr(0, slash);
833 string lenstr = subnet4o6.substr(slash + 1);
834
835 uint8_t len = 128;
836 try {
837 len = boost::lexical_cast<unsigned int>(lenstr.c_str());
838 } catch (const boost::bad_lexical_cast &) {
839 isc_throw(DhcpConfigError, "Invalid prefix length specified in "
840 "4o6-subnet parameter: " << subnet4o6 << ", expected 0..128 value");
841 }
842 subnet4->get4o6().setSubnet4o6(IOAddress(prefix), len);
843 subnet4->get4o6().enabled(true);
844 }
845
846 // Try 4o6 specific parameter: 4o6-interface-id
847 std::string ifaceid = getString(params, "4o6-interface-id");
848 if (!ifaceid.empty()) {
849 OptionBuffer tmp(ifaceid.begin(), ifaceid.end());
851 subnet4->get4o6().setInterfaceId(opt);
852 subnet4->get4o6().enabled(true);
853 }
854
857
858 // Here globally defined options were merged to the subnet specific
859 // options but this is no longer the case (they have a different
860 // and not consecutive priority).
861
862 // Copy options to the subnet configuration.
863 options_->copyTo(*subnet4->getCfgOption());
864}
865
866//**************************** Subnets4ListConfigParser **********************
867
868size_t
870 size_t cnt = 0;
871 BOOST_FOREACH(ConstElementPtr subnet_json, subnets_list->listValue()) {
872
873 Subnet4ConfigParser parser;
874 Subnet4Ptr subnet = parser.parse(subnet_json);
875 if (subnet) {
876
877 // Adding a subnet to the Configuration Manager may fail if the
878 // subnet id is invalid (duplicate). Thus, we catch exceptions
879 // here to append a position in the configuration string.
880 try {
881 cfg->getCfgSubnets4()->add(subnet);
882 cnt++;
883 } catch (const std::exception& ex) {
884 isc_throw(DhcpConfigError, ex.what() << " ("
885 << subnet_json->getPosition() << ")");
886 }
887 }
888 }
889 return (cnt);
890}
891
892size_t
894 data::ConstElementPtr subnets_list) {
895 size_t cnt = 0;
896 BOOST_FOREACH(ConstElementPtr subnet_json, subnets_list->listValue()) {
897
898 Subnet4ConfigParser parser;
899 Subnet4Ptr subnet = parser.parse(subnet_json);
900 if (subnet) {
901 try {
902 subnets.push_back(subnet);
903 ++cnt;
904 } catch (const std::exception& ex) {
905 isc_throw(DhcpConfigError, ex.what() << " ("
906 << subnet_json->getPosition() << ")");
907 }
908 }
909 }
910 return (cnt);
911}
912
913
914//**************************** Pool6Parser *********************************
915
917Pool6Parser::poolMaker (IOAddress &addr, uint32_t len, int32_t ptype)
918{
919 return (PoolPtr(new Pool6(static_cast<isc::dhcp::Lease::Type>
920 (ptype), addr, len)));
921}
922
924Pool6Parser::poolMaker (IOAddress &min, IOAddress &max, int32_t ptype)
925{
926 return (PoolPtr(new Pool6(static_cast<isc::dhcp::Lease::Type>
927 (ptype), min, max)));
928}
929
930
931//**************************** Pool6ListParser ***************************
932
933void
935 BOOST_FOREACH(ConstElementPtr pool, pools_list->listValue()) {
936 Pool6Parser parser;
937 parser.parse(pools, pool, AF_INET6);
938 }
939}
940
941//**************************** PdPoolParser ******************************
942
944}
945
946void
948 std::string addr_str = getString(pd_pool_, "prefix");
949
950 uint8_t prefix_len = getUint8(pd_pool_, "prefix-len");
951
952 uint8_t delegated_len = getUint8(pd_pool_, "delegated-len");
953
954 std::string excluded_prefix_str = "::";
955 if (pd_pool_->contains("excluded-prefix")) {
956 excluded_prefix_str = getString(pd_pool_, "excluded-prefix");
957 }
958
959 uint8_t excluded_prefix_len = 0;
960 if (pd_pool_->contains("excluded-prefix-len")) {
961 excluded_prefix_len = getUint8(pd_pool_, "excluded-prefix-len");
962 }
963
964 ConstElementPtr option_data = pd_pool_->get("option-data");
965 if (option_data) {
966 OptionDataListParser opts_parser(AF_INET6);
967 opts_parser.parse(options_, option_data);
968 }
969
970 ConstElementPtr user_context = pd_pool_->get("user-context");
971 if (user_context) {
972 user_context_ = user_context;
973 }
974
975 ConstElementPtr client_class = pd_pool_->get("client-class");
976 if (client_class) {
977 client_class_ = client_class;
978 }
979
980 ConstElementPtr class_list = pd_pool_->get("require-client-classes");
981
982 // Check the pool parameters. It will throw an exception if any
983 // of the required parameters are invalid.
984 try {
985 // Attempt to construct the local pool.
986 pool_.reset(new Pool6(IOAddress(addr_str),
987 prefix_len,
988 delegated_len,
989 IOAddress(excluded_prefix_str),
990 excluded_prefix_len));
991 // Merge options specified for a pool into pool configuration.
992 options_->copyTo(*pool_->getCfgOption());
993 } catch (const std::exception& ex) {
994 // Some parameters don't exist or are invalid. Since we are not
995 // aware whether they don't exist or are invalid, let's append
996 // the position of the pool map element.
998 << " (" << pd_pool_->getPosition() << ")");
999 }
1000
1001 if (user_context_) {
1002 pool_->setContext(user_context_);
1003 }
1004
1005 if (client_class_) {
1006 string cclass = client_class_->stringValue();
1007 if (!cclass.empty()) {
1008 pool_->allowClientClass(cclass);
1009 }
1010 }
1011
1012 if (class_list) {
1013 const std::vector<data::ElementPtr>& classes = class_list->listValue();
1014 for (auto cclass = classes.cbegin();
1015 cclass != classes.cend(); ++cclass) {
1016 if (((*cclass)->getType() != Element::string) ||
1017 (*cclass)->stringValue().empty()) {
1018 isc_throw(DhcpConfigError, "invalid class name ("
1019 << (*cclass)->getPosition() << ")");
1020 }
1021 pool_->requireClientClass((*cclass)->stringValue());
1022 }
1023 }
1024
1025 // Add the local pool to the external storage ptr.
1026 pools->push_back(pool_);
1027}
1028
1029//**************************** PdPoolsListParser ************************
1030
1031void
1033 // Loop through the list of pd pools.
1034 BOOST_FOREACH(ConstElementPtr pd_pool, pd_pool_list->listValue()) {
1035 PdPoolParser parser;
1036 parser.parse(pools, pd_pool);
1037 }
1038}
1039
1040//**************************** Subnet6ConfigParser ***********************
1041
1043 :SubnetConfigParser(AF_INET6) {
1044}
1045
1049 ConstElementPtr pools = subnet->get("pools");
1050 if (pools) {
1051 Pools6ListParser parser;
1052 parser.parse(pools_, pools);
1053 }
1054 ConstElementPtr pd_pools = subnet->get("pd-pools");
1055 if (pd_pools) {
1056 PdPoolsListParser parser;
1057 parser.parse(pools_, pd_pools);
1058 }
1059
1060 SubnetPtr generic = SubnetConfigParser::parse(subnet);
1061
1062 if (!generic) {
1063 // Sanity check: not supposed to fail.
1065 "Failed to create an IPv6 subnet (" <<
1066 subnet->getPosition() << ")");
1067 }
1068
1069 Subnet6Ptr sn6ptr = boost::dynamic_pointer_cast<Subnet6>(subnet_);
1070 if (!sn6ptr) {
1071 // If we hit this, it is a programming error.
1073 "Invalid Subnet6 cast in Subnet6ConfigParser::parse");
1074 }
1075
1076 // Set relay information if it was provided
1077 if (relay_info_) {
1078 sn6ptr->setRelayInfo(*relay_info_);
1079 }
1080
1081 // Parse Host Reservations for this subnet if any.
1082 ConstElementPtr reservations = subnet->get("reservations");
1083 if (reservations) {
1084 HostCollection hosts;
1086 parser.parse(subnet_->getID(), reservations, hosts);
1087 for (auto h = hosts.begin(); h != hosts.end(); ++h) {
1088 CfgMgr::instance().getStagingCfg()->getCfgHosts()->add(*h);
1089 }
1090 }
1091
1092 return (sn6ptr);
1093}
1094
1095// Unused?
1096void
1098 asiolink::IOAddress& addr) {
1099 LOG_WARN(dhcpsrv_logger, DHCPSRV_CFGMGR_OPTION_DUPLICATE)
1100 .arg(code).arg(addr.toText());
1101}
1102
1103void
1105 asiolink::IOAddress addr, uint8_t len) {
1106 // Get all 'time' parameters using inheritance.
1107 // If the subnet-specific value is defined then use it, else
1108 // use the global value. The global value must always be
1109 // present. If it is not, it is an internal error and exception
1110 // is thrown.
1111 Triplet<uint32_t> t1 = getInteger(params, "renew-timer");
1112 Triplet<uint32_t> t2 = getInteger(params, "rebind-timer");
1113 Triplet<uint32_t> pref = getInteger(params, "preferred-lifetime");
1114 Triplet<uint32_t> valid = getInteger(params, "valid-lifetime");
1115
1116 // Subnet ID is optional. If it is not supplied the value of 0 is used,
1117 // which means autogenerate. The value was inserted earlier by calling
1118 // SimpleParser6::setAllDefaults.
1119 SubnetID subnet_id = static_cast<SubnetID>(getInteger(params, "id"));
1120
1121 // We want to log whether rapid-commit is enabled, so we get this
1122 // before the actual subnet creation.
1123 bool rapid_commit = getBoolean(params, "rapid-commit");
1124
1125 std::ostringstream output;
1126 output << addr << "/" << static_cast<int>(len)
1127 << " with params t1=" << t1 << ", t2="
1128 << t2 << ", preferred-lifetime=" << pref
1129 << ", valid-lifetime=" << valid
1130 << ", rapid-commit is " << (rapid_commit ? "enabled" : "disabled");
1131
1132
1133 LOG_INFO(dhcpsrv_logger, DHCPSRV_CFGMGR_NEW_SUBNET6).arg(output.str());
1134
1135 // Create a new subnet.
1136 Subnet6* subnet6 = new Subnet6(addr, len, t1, t2, pref, valid,
1137 subnet_id);
1138 subnet_.reset(subnet6);
1139
1140 // Enable or disable Rapid Commit option support for the subnet.
1141 subnet6->setRapidCommit(rapid_commit);
1142
1143 // Get interface-id option content. For now we support string
1144 // representation only
1145 std::string ifaceid = getString(params, "interface-id");
1146 std::string iface = getString(params, "interface");
1147
1148 // Specifying both interface for locally reachable subnets and
1149 // interface id for relays is mutually exclusive. Need to test for
1150 // this condition.
1151 if (!ifaceid.empty() && !iface.empty()) {
1153 "parser error: interface (defined for locally reachable "
1154 "subnets) and interface-id (defined for subnets reachable"
1155 " via relays) cannot be defined at the same time for "
1156 "subnet " << addr << "/" << (int)len << "("
1157 << params->getPosition() << ")");
1158 }
1159
1160 // Configure interface-id for remote interfaces, if defined
1161 if (!ifaceid.empty()) {
1162 OptionBuffer tmp(ifaceid.begin(), ifaceid.end());
1164 subnet6->setInterfaceId(opt);
1165 }
1166
1167 // Get interface name. If it is defined, then the subnet is available
1168 // directly over specified network interface.
1169 if (!iface.empty()) {
1170 if (!IfaceMgr::instance().getIface(iface)) {
1171 ConstElementPtr error = params->get("interface");
1172 isc_throw(DhcpConfigError, "Specified network interface name " << iface
1173 << " for subnet " << subnet6->toText()
1174 << " is not present in the system ("
1175 << error->getPosition() << ")");
1176 }
1177
1178 subnet6->setIface(iface);
1179 }
1180
1181 // Let's set host reservation mode. If not specified, the default value of
1182 // all will be used.
1183 try {
1184 std::string hr_mode = getString(params, "reservation-mode");
1185 subnet6->setHostReservationMode(hrModeFromText(hr_mode));
1186 } catch (const BadValue& ex) {
1187 isc_throw(DhcpConfigError, "Failed to process specified value "
1188 " of reservation-mode parameter: " << ex.what()
1189 << "(" << getPosition("reservation-mode", params) << ")");
1190 }
1191
1192 // Try setting up client class.
1193 string client_class = getString(params, "client-class");
1194 if (!client_class.empty()) {
1195 subnet6->allowClientClass(client_class);
1196 }
1197
1198 // Try setting up required client classes.
1199 ConstElementPtr class_list = params->get("require-client-classes");
1200 if (class_list) {
1201 const std::vector<data::ElementPtr>& classes = class_list->listValue();
1202 for (auto cclass = classes.cbegin();
1203 cclass != classes.cend(); ++cclass) {
1204 if (((*cclass)->getType() != Element::string) ||
1205 (*cclass)->stringValue().empty()) {
1206 isc_throw(DhcpConfigError, "invalid class name ("
1207 << (*cclass)->getPosition() << ")");
1208 }
1209 subnet6->requireClientClass((*cclass)->stringValue());
1210 }
1211 }
1212
1215
1216 // Copy options to the subnet configuration.
1217 options_->copyTo(*subnet6->getCfgOption());
1218}
1219
1220//**************************** Subnet6ListConfigParser ********************
1221
1222size_t
1224 size_t cnt = 0;
1225 BOOST_FOREACH(ConstElementPtr subnet_json, subnets_list->listValue()) {
1226
1227 Subnet6ConfigParser parser;
1228 Subnet6Ptr subnet = parser.parse(subnet_json);
1229
1230 // Adding a subnet to the Configuration Manager may fail if the
1231 // subnet id is invalid (duplicate). Thus, we catch exceptions
1232 // here to append a position in the configuration string.
1233 try {
1234 cfg->getCfgSubnets6()->add(subnet);
1235 cnt++;
1236 } catch (const std::exception& ex) {
1237 isc_throw(DhcpConfigError, ex.what() << " ("
1238 << subnet_json->getPosition() << ")");
1239 }
1240 }
1241 return (cnt);
1242}
1243
1244size_t
1246 ConstElementPtr subnets_list) {
1247 size_t cnt = 0;
1248 BOOST_FOREACH(ConstElementPtr subnet_json, subnets_list->listValue()) {
1249
1250 Subnet6ConfigParser parser;
1251 Subnet6Ptr subnet = parser.parse(subnet_json);
1252 try {
1253 subnets.push_back(subnet);
1254 ++cnt;
1255 } catch (const std::exception& ex) {
1256 isc_throw(DhcpConfigError, ex.what() << " ("
1257 << subnet_json->getPosition() << ")");
1258 }
1259 }
1260 return (cnt);
1261}
1262
1263
1264//**************************** D2ClientConfigParser **********************
1265
1267D2ClientConfigParser::getProtocol(ConstElementPtr scope,
1268 const std::string& name) {
1271 (scope, name, "NameChangeRequest protocol"));
1272}
1273
1275D2ClientConfigParser::getFormat(ConstElementPtr scope,
1276 const std::string& name) {
1279 (scope, name, "NameChangeRequest format"));
1280}
1281
1283D2ClientConfigParser::getMode(ConstElementPtr scope,
1284 const std::string& name) {
1287 (scope, name, "ReplaceClientName mode"));
1288}
1289
1292 D2ClientConfigPtr new_config;
1293
1294 // Get all parameters that are needed to create the D2ClientConfig.
1295 bool enable_updates = getBoolean(client_config, "enable-updates");
1296
1297 IOAddress server_ip = getAddress(client_config, "server-ip");
1298
1299 uint32_t server_port = getUint32(client_config, "server-port");
1300
1301 std::string sender_ip_str = getString(client_config, "sender-ip");
1302
1303 uint32_t sender_port = getUint32(client_config, "sender-port");
1304
1305 uint32_t max_queue_size = getUint32(client_config, "max-queue-size");
1306
1307 dhcp_ddns::NameChangeProtocol ncr_protocol =
1308 getProtocol(client_config, "ncr-protocol");
1309
1310 dhcp_ddns::NameChangeFormat ncr_format =
1311 getFormat(client_config, "ncr-format");
1312
1313 bool override_no_update =
1314 getBoolean(client_config, "override-no-update");
1315
1316 bool override_client_update =
1317 getBoolean(client_config, "override-client-update");
1318
1319 D2ClientConfig::ReplaceClientNameMode replace_client_name_mode =
1320 getMode(client_config, "replace-client-name");
1321
1322 std::string generated_prefix =
1323 getString(client_config, "generated-prefix");
1324
1325 std::string hostname_char_set =
1326 getString(client_config, "hostname-char-set");
1327
1328 std::string hostname_char_replacement =
1329 getString(client_config, "hostname-char-replacement");
1330
1331 // qualifying-suffix is the only parameter which has no default
1332 std::string qualifying_suffix = "";
1333 bool found_qualifying_suffix = false;
1334 if (client_config->contains("qualifying-suffix")) {
1335 qualifying_suffix = getString(client_config, "qualifying-suffix");
1336 found_qualifying_suffix = true;
1337 }
1338
1339 IOAddress sender_ip(0);
1340 if (sender_ip_str.empty()) {
1341 // The default sender IP depends on the server IP family
1342 sender_ip = (server_ip.isV4() ? IOAddress::IPV4_ZERO_ADDRESS() :
1344 } else {
1345 try {
1346 sender_ip = IOAddress(sender_ip_str);
1347 } catch (const std::exception& ex) {
1348 isc_throw(DhcpConfigError, "invalid address (" << sender_ip_str
1349 << ") specified for parameter 'sender-ip' ("
1350 << getPosition("sender-ip", client_config) << ")");
1351 }
1352 }
1353
1354 // Qualifying-suffix is required when updates are enabled
1355 if (enable_updates && !found_qualifying_suffix) {
1357 "parameter 'qualifying-suffix' is required when "
1358 "updates are enabled ("
1359 << client_config->getPosition() << ")");
1360 }
1361
1362 // Now we check for logical errors. This repeats what is done in
1363 // D2ClientConfig::validate(), but doing it here permits us to
1364 // emit meaningful parameter position info in the error.
1365 if (ncr_format != dhcp_ddns::FMT_JSON) {
1366 isc_throw(D2ClientError, "D2ClientConfig error: NCR Format: "
1367 << dhcp_ddns::ncrFormatToString(ncr_format)
1368 << " is not supported. ("
1369 << getPosition("ncr-format", client_config) << ")");
1370 }
1371
1372 if (ncr_protocol != dhcp_ddns::NCR_UDP) {
1373 isc_throw(D2ClientError, "D2ClientConfig error: NCR Protocol: "
1374 << dhcp_ddns::ncrProtocolToString(ncr_protocol)
1375 << " is not supported. ("
1376 << getPosition("ncr-protocol", client_config) << ")");
1377 }
1378
1379 if (sender_ip.getFamily() != server_ip.getFamily()) {
1381 "D2ClientConfig error: address family mismatch: "
1382 << "server-ip: " << server_ip.toText()
1383 << " is: " << (server_ip.isV4() ? "IPv4" : "IPv6")
1384 << " while sender-ip: " << sender_ip.toText()
1385 << " is: " << (sender_ip.isV4() ? "IPv4" : "IPv6")
1386 << " (" << getPosition("sender-ip", client_config) << ")");
1387 }
1388
1389 if (server_ip == sender_ip && server_port == sender_port) {
1391 "D2ClientConfig error: server and sender cannot"
1392 " share the exact same IP address/port: "
1393 << server_ip.toText() << "/" << server_port
1394 << " (" << getPosition("sender-ip", client_config) << ")");
1395 }
1396
1397 try {
1398 // Attempt to create the new client config.
1399 new_config.reset(new D2ClientConfig(enable_updates,
1400 server_ip,
1401 server_port,
1402 sender_ip,
1403 sender_port,
1404 max_queue_size,
1405 ncr_protocol,
1406 ncr_format,
1407 override_no_update,
1408 override_client_update,
1409 replace_client_name_mode,
1410 generated_prefix,
1411 qualifying_suffix,
1412 hostname_char_set,
1413 hostname_char_replacement));
1414 } catch (const std::exception& ex) {
1415 isc_throw(DhcpConfigError, ex.what() << " ("
1416 << client_config->getPosition() << ")");
1417 }
1418
1419 // Add user context
1420 ConstElementPtr user_context = client_config->get("user-context");
1421 if (user_context) {
1422 new_config->setContext(user_context);
1423 }
1424
1425 return(new_config);
1426}
1427
1430 // enable-updates is unconditionally required
1431 { "server-ip", Element::string, "127.0.0.1" },
1432 { "server-port", Element::integer, "53001" },
1433 // default sender-ip depends on server-ip family, so we leave default blank
1434 // parser knows to use the appropriate ZERO address based on server-ip
1435 { "sender-ip", Element::string, "" },
1436 { "sender-port", Element::integer, "0" },
1437 { "max-queue-size", Element::integer, "1024" },
1438 { "ncr-protocol", Element::string, "UDP" },
1439 { "ncr-format", Element::string, "JSON" },
1440 { "override-no-update", Element::boolean, "false" },
1441 { "override-client-update", Element::boolean, "false" },
1442 { "replace-client-name", Element::string, "never" },
1443 { "generated-prefix", Element::string, "myhost" },
1444 { "hostname-char-set", Element::string, "" },
1445 { "hostname-char-replacement", Element::string, "" }
1446 // qualifying-suffix has no default
1447};
1448
1449size_t
1451 ElementPtr mutable_d2 = boost::const_pointer_cast<Element>(d2_config);
1453}
1454
1455}; // namespace dhcp
1456}; // namespace isc
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.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
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.
target_type getAndConvert(isc::data::ConstElementPtr scope, const std::string &name, const std::string &type_name)
Returns a converted value from a scope.
static const data::Element::Position & getPosition(const std::string &name, const data::ConstElementPtr parent)
Utility method that returns position of an element.
uint8_t getUint8(ConstElementPtr scope, const std::string &name)
Get an uint8_t value.
static isc::asiolink::IOAddress getAddress(const ConstElementPtr &scope, const std::string &name)
Returns a IOAddress parameter from a scope.
static std::string getString(isc::data::ConstElementPtr scope, const std::string &name)
Returns a string parameter from a scope.
uint32_t getUint32(isc::data::ConstElementPtr scope, const std::string &name)
Returns a value converted to uint32_t.
static bool getBoolean(isc::data::ConstElementPtr scope, const std::string &name)
Returns a boolean 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.
Represents selection of interfaces for DHCP server.
Definition: cfg_iface.h:130
Wrapper class that holds MAC/hardware address sources.
void add(uint32_t source)
Adds additional MAC/hardware address acquisition.
void clear()
Removes any configured MAC/Hardware address sources.
static uint32_t MACSourceFromText(const std::string &name)
Attempts to convert known hardware address sources to uint32_t.
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition: cfgmgr.cc:25
SrvConfigPtr getStagingCfg()
Returns a pointer to the staging configuration.
Definition: cfgmgr.cc:160
Represents option data configuration for the DHCP server.
Definition: cfg_option.h:248
void parse(SrvConfig &srv_cfg, isc::data::ConstElementPtr value)
"Parses" control-socket structure
Definition: dhcp_parsers.cc:69
D2ClientConfigPtr parse(isc::data::ConstElementPtr d2_client_cfg)
Parses a given dhcp-ddns element into D2ClientConfig.
static const isc::data::SimpleDefaults D2_CLIENT_CONFIG_DEFAULTS
Defaults for the D2 client configuration.
Definition: dhcp_parsers.h:810
static size_t setAllDefaults(isc::data::ConstElementPtr d2_config)
Sets all defaults for D2 client configuration.
Acts as a storage vault for D2 client configuration.
Definition: d2_client_cfg.h:53
static ReplaceClientNameMode stringToReplaceClientNameMode(const std::string &mode_str)
Converts labels to ReplaceClientNameMode enum values.
ReplaceClientNameMode
Defines the client name replacement modes.
Definition: d2_client_cfg.h:72
An exception that is thrown if an error occurs while configuring the D2 DHCP DDNS client.
Definition: d2_client_cfg.h:34
To be removed. Please use ConfigError instead.
Parser for a list of host reservations for a subnet.
void parse(const SubnetID &subnet_id, isc::data::ConstElementPtr hr_list, HostCollection &hosts_list)
Parses a list of host reservation entries for a subnet.
static IfaceMgr & instance()
IfaceMgr is a singleton class.
Definition: iface_mgr.cc:53
static void setRuntimeOptionDefs(const OptionDefSpaceContainer &defs)
Copies option definitions created at runtime.
Definition: libdhcp++.cc:234
static OptionDefinitionPtr getOptionDef(const std::string &space, const uint16_t code)
Return the first option definition matching a particular option code.
Definition: libdhcp++.cc:144
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:184
static uint32_t optionSpaceToVendorId(const std::string &option_space)
Converts option space name to vendor id.
Definition: libdhcp++.cc:916
void parse(CfgMACSource &mac_sources, isc::data::ConstElementPtr value)
parses parameters value
Definition: dhcp_parsers.cc:38
void setRapidCommit(const bool rapid_commit)
Enables or disables Rapid Commit option support for the subnet.
Definition: network.h:479
void setInterfaceId(const OptionPtr &ifaceid)
sets interface-id option (if defined)
Definition: network.h:463
Holds optional information about relay.
Definition: network.h:59
void setHostReservationMode(HRMode mode)
Sets host reservation mode.
Definition: network.h:298
HRMode
Specifies allowed host reservation mode.
Definition: network.h:91
@ HR_DISABLED
None - host reservation is disabled.
Definition: network.h:95
@ HR_OUT_OF_POOL
Only out-of-pool reservations is allowed.
Definition: network.h:100
@ HR_GLOBAL
Only global reservations are allowed.
Definition: network.h:104
@ HR_ALL
Both out-of-pool and in-pool reservations are allowed.
Definition: network.h:112
boost::shared_ptr< Network::RelayInfo > RelayInfoPtr
Pointer to the RelayInfo structure.
Definition: network.h:116
void requireClientClass(const isc::dhcp::ClientClass &class_name)
Adds class class_name to classes required to be evaluated.
Definition: network.cc:90
void allowClientClass(const isc::dhcp::ClientClass &class_name)
Sets the supported class to class class_name.
Definition: network.cc:85
void setIface(const std::string &iface_name)
Sets local name of the interface for which this network is selected.
Definition: network.h:137
CfgOptionPtr getCfgOption()
Returns pointer to the option data configuration for this subnet.
Definition: network.h:303
Parser for option data values within a subnet.
void parse(const CfgOptionPtr &cfg, isc::data::ConstElementPtr option_data_list)
Parses a list of options, instantiates them and stores in cfg.
void parse(CfgOptionDefPtr cfg, isc::data::ConstElementPtr def_list)
Parses a list of option definitions, create them and store in cfg.
Parser for a single option definition.
Definition: dhcp_parsers.h:228
OptionDefinitionTuple parse(isc::data::ConstElementPtr option_def)
Parses an entry that describes single option definition.
Base class representing a DHCP option definition.
static bool validateName(const std::string &name)
Checks that the provided option space name is valid.
Definition: option_space.cc:26
Universe
defines option universe DHCPv4 or DHCPv6
Definition: option.h:67
Parser for IPv6 prefix delegation definitions.
Definition: dhcp_parsers.h:647
PdPoolParser()
Constructor.
void parse(PoolStoragePtr pools, data::ConstElementPtr pd_pool_)
Builds a prefix delegation pool from the given configuration.
Parser for a list of prefix delegation pools.
Definition: dhcp_parsers.h:690
void parse(PoolStoragePtr pools, data::ConstElementPtr pd_pool_list)
Parse configuration entries.
static const size_t MAX_SNAME_LEN
length of the SNAME field in DHCPv4 message
Definition: pkt4.h:45
static const size_t MAX_FILE_LEN
length of the FILE field in DHCPv4 message
Definition: pkt4.h:48
Parser for IPv4 pool definitions.
Definition: dhcp_parsers.h:322
PoolPtr poolMaker(asiolink::IOAddress &addr, uint32_t len, int32_t ignored)
Creates a Pool4 object given a IPv4 prefix and the prefix length.
Pool information for IPv4 addresses.
Definition: pool.h:243
Parser for IPv6 pool definitions.
Definition: dhcp_parsers.h:592
PoolPtr poolMaker(asiolink::IOAddress &addr, uint32_t len, int32_t ptype)
Creates a Pool6 object given a IPv6 prefix and the prefix length.
Pool information for IPv6 addresses and prefixes.
Definition: pool.h:272
virtual void parse(PoolStoragePtr pools, isc::data::ConstElementPtr pool_structure, const uint16_t address_family)
parses the actual structure
virtual PoolPtr poolMaker(isc::asiolink::IOAddress &addr, uint32_t len, int32_t ptype=0)=0
Creates a Pool object given a IPv4 prefix and the prefix length.
Specialization of the pool list parser for DHCPv4.
Definition: dhcp_parsers.h:369
void parse(PoolStoragePtr pools, data::ConstElementPtr pools_list)
parses the actual structure
Specialization of the pool list parser for DHCPv6.
Definition: dhcp_parsers.h:617
void parse(PoolStoragePtr pools, data::ConstElementPtr pools_list)
parses the actual structure
parser for additional relay information
Definition: dhcp_parsers.h:389
RelayInfoParser(const isc::dhcp::Option::Universe &family)
constructor
void addAddress(const std::string &name, const std::string &address_str, isc::data::ConstElementPtr relay_elem, const isc::dhcp::Network::RelayInfoPtr &relay_info)
Attempts to add an IP address to list of relay addresses.
void parse(const isc::dhcp::Network::RelayInfoPtr &relay_info, isc::data::ConstElementPtr relay_elem)
parses the actual relay parameters
Specifies current DHCP configuration.
Definition: srv_config.h:44
void setControlSocketInfo(const isc::data::ConstElementPtr &control_socket)
Sets information about the control socket.
Definition: srv_config.h:359
void initSubnet(data::ConstElementPtr params, asiolink::IOAddress addr, uint8_t len)
Instantiates the IPv4 Subnet based on a given IPv4 address and prefix length.
Subnet4Ptr parse(data::ConstElementPtr subnet)
Parses a single IPv4 subnet configuration and adds to the Configuration Manager.
A configuration holder for IPv4 subnet.
Definition: subnet.h:471
virtual void duplicate_option_warning(uint32_t code, asiolink::IOAddress &addr)
Issues a DHCP6 server specific warning regarding duplicate subnet options.
Subnet6Ptr parse(data::ConstElementPtr subnet)
Parses a single IPv6 subnet configuration and adds to the Configuration Manager.
void initSubnet(isc::data::ConstElementPtr params, isc::asiolink::IOAddress addr, uint8_t len)
Instantiates the IPv6 Subnet based on a given IPv6 address and prefix length.
A configuration holder for IPv6 subnet.
Definition: subnet.h:636
this class parses a single subnet
Definition: dhcp_parsers.h:453
isc::dhcp::SubnetPtr subnet_
Pointer to the created subnet object.
Definition: dhcp_parsers.h:512
CfgOptionPtr options_
Pointer to the options configuration.
Definition: dhcp_parsers.h:521
virtual void initSubnet(isc::data::ConstElementPtr params, isc::asiolink::IOAddress addr, uint8_t len)=0
Instantiates the subnet based on a given IP prefix and prefix length.
SubnetPtr parse(isc::data::ConstElementPtr subnet)
parses a subnet description and returns Subnet{4,6} structure
isc::dhcp::Network::RelayInfoPtr relay_info_
Pointer to relay information.
Definition: dhcp_parsers.h:518
SubnetConfigParser(uint16_t family)
constructor
uint16_t address_family_
Address family: AF_INET or AF_INET6.
Definition: dhcp_parsers.h:515
PoolStoragePtr pools_
Storage for pools belonging to this subnet.
Definition: dhcp_parsers.h:509
static Network::HRMode hrModeFromText(const std::string &txt)
Attempts to convert text representation to HRMode enum.
virtual std::string toText() const
Returns textual representation of the subnet (e.g.
Definition: subnet.cc:139
size_t parse(SrvConfigPtr cfg, data::ConstElementPtr subnets_list)
parses contents of the list
size_t parse(SrvConfigPtr cfg, data::ConstElementPtr subnets_list)
parses contents of the list
This template specifies a parameter value.
Definition: triplet.h:36
bool unspecified() const
Check if the value has been specified.
Definition: triplet.h:128
@ D6O_INTERFACE_ID
Definition: dhcp6.h:38
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition: macros.h:20
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition: macros.h:26
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:23
std::vector< SimpleDefault > SimpleDefaults
This specifies all default values in a given scope (e.g. a subnet)
boost::shared_ptr< Element > ElementPtr
Definition: data.h:22
NameChangeProtocol stringToNcrProtocol(const std::string &protocol_str)
Function which converts labels to NameChangeProtocol enum values.
Definition: ncr_io.cc:17
NameChangeFormat
Defines the list of data wire formats supported.
Definition: ncr_msg.h:60
NameChangeProtocol
Defines the list of socket protocols supported.
Definition: ncr_io.h:66
std::string ncrProtocolToString(NameChangeProtocol protocol)
Function which converts NameChangeProtocol enums to text labels.
Definition: ncr_io.cc:30
NameChangeFormat stringToNcrFormat(const std::string &fmt_str)
Function which converts labels to NameChangeFormat enum values.
Definition: ncr_msg.cc:27
std::string ncrFormatToString(NameChangeFormat format)
Function which converts NameChangeFormat enums to text labels.
Definition: ncr_msg.cc:36
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition: dhcpsrv_log.h:56
boost::multi_index_container< Subnet6Ptr, boost::multi_index::indexed_by< boost::multi_index::random_access< boost::multi_index::tag< SubnetRandomAccessIndexTag > >, 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 > > > > Subnet6Collection
A collection of Subnet6 objects.
Definition: subnet.h:843
boost::shared_ptr< Subnet > SubnetPtr
A generic pointer to either Subnet4 or Subnet6 object.
Definition: subnet.h:455
boost::shared_ptr< Subnet4 > Subnet4Ptr
A pointer to a Subnet4 object.
Definition: subnet.h:464
std::vector< PoolPtr > PoolStorage
a collection of pools
Definition: dhcp_parsers.h:263
boost::shared_ptr< D2ClientConfig > D2ClientConfigPtr
Defines a pointer for D2ClientConfig instances.
boost::shared_ptr< CfgOption > CfgOptionPtr
Non-const pointer.
Definition: cfg_option.h:497
boost::shared_ptr< CfgOptionDef > CfgOptionDefPtr
Non-const pointer.
boost::shared_ptr< Subnet6 > Subnet6Ptr
A pointer to a Subnet6 object.
Definition: subnet.h:629
boost::shared_ptr< SrvConfig > SrvConfigPtr
Non-const pointer to the SrvConfig.
Definition: srv_config.h:707
std::vector< HostPtr > HostCollection
Collection of the Host objects.
Definition: host.h:734
const int DHCPSRV_DBG_TRACE_DETAIL
Additional information.
Definition: dhcpsrv_log.h:38
boost::shared_ptr< OptionDefinition > OptionDefinitionPtr
Pointer to option definition object.
boost::shared_ptr< PoolStorage > PoolStoragePtr
Definition: dhcp_parsers.h:264
boost::shared_ptr< Pool > PoolPtr
a pointer to either IPv4 or IPv6 Pool
Definition: pool.h:405
std::pair< isc::dhcp::OptionDefinitionPtr, std::string > OptionDefinitionTuple
Definition: dhcp_parsers.h:223
uint32_t SubnetID
Unique identifier for a subnet (both v4 and v6)
Definition: lease.h:24
boost::multi_index_container< Subnet4Ptr, boost::multi_index::indexed_by< boost::multi_index::random_access< boost::multi_index::tag< SubnetRandomAccessIndexTag > >, 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 > > > > Subnet4Collection
A collection of Subnet4 objects.
Definition: subnet.h:798
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
Definition: option.h:25
boost::shared_ptr< Option > OptionPtr
Definition: option.h:38
vector< string > tokens(const std::string &text, const std::string &delim, bool escape)
Split String into Tokens.
Definition: strutil.cc:77
Definition: edns.h:19
Defines the logger used by the top-level component of kea-dhcp-ddns.
Type
Type of lease or pool.
Definition: lease.h:38