13#include <boost/lexical_cast.hpp>
15#include <sys/socket.h>
35const std::set<std::string>&
36getSupportedParams4(
const bool identifiers_only =
false) {
38 static std::set<std::string> identifiers_set;
40 static std::set<std::string> params_set;
43 if (identifiers_set.empty()) {
44 identifiers_set.insert(
"hw-address");
45 identifiers_set.insert(
"duid");
46 identifiers_set.insert(
"circuit-id");
47 identifiers_set.insert(
"client-id");
48 identifiers_set.insert(
"flex-id");
51 if (params_set.empty()) {
52 params_set = identifiers_set;
53 params_set.insert(
"hostname");
54 params_set.insert(
"ip-address");
55 params_set.insert(
"option-data");
56 params_set.insert(
"next-server");
57 params_set.insert(
"server-hostname");
58 params_set.insert(
"boot-file-name");
59 params_set.insert(
"client-classes");
60 params_set.insert(
"user-context");
62 return (identifiers_only ? identifiers_set : params_set);
73const std::set<std::string>&
74getSupportedParams6(
const bool identifiers_only =
false) {
76 static std::set<std::string> identifiers_set;
78 static std::set<std::string> params_set;
81 if (identifiers_set.empty()) {
82 identifiers_set.insert(
"hw-address");
83 identifiers_set.insert(
"duid");
84 identifiers_set.insert(
"flex-id");
87 if (params_set.empty()) {
88 params_set = identifiers_set;
89 params_set.insert(
"hostname");
90 params_set.insert(
"ip-addresses");
91 params_set.insert(
"prefixes");
92 params_set.insert(
"excluded-prefixes");
93 params_set.insert(
"option-data");
94 params_set.insert(
"client-classes");
95 params_set.insert(
"user-context");
97 return (identifiers_only ? identifiers_set : params_set);
108parsePrefix(std::string prefix,
IOAddress& addr, uint8_t& len, std::string msg) {
111 size_t len_pos = prefix.find(
'/');
112 if (len_pos == std::string::npos) {
113 isc_throw(DhcpConfigError, msg <<
" requires prefix length "
114 <<
"be specified in '" << prefix <<
"'");
115 }
else if (len_pos >= prefix.length() - 1) {
118 isc_throw(DhcpConfigError,
"prefix '" << prefix
119 <<
"' requires length after '/'");
127 unsigned int prefix_len = len;
129 prefix_len = boost::lexical_cast<unsigned int>(prefix.substr(len_pos + 1));
130 }
catch (
const boost::bad_lexical_cast&) {
131 isc_throw(DhcpConfigError,
"prefix length value '"
132 << prefix.substr(len_pos + 1) <<
"' is invalid");
134 if ((prefix_len == 0) || (prefix_len > 128)) {
136 "'prefix-len' value must be in range of [1..128]");
138 len =
static_cast<uint8_t
>(prefix_len);
142 prefix.erase(len_pos);
147 if (first_address != addr) {
149 <<
" exceeds prefix/prefix-len pair: " << first_address
150 <<
"/" << prefix_len);
160 bool encapsulate_options) {
161 return (
parseInternal(subnet_id, reservation_data, encapsulate_options));
168 std::string identifier;
169 std::string identifier_name;
170 std::string hostname;
177 for (
auto const& element : reservation_data->mapValue()) {
181 " parameter '" << element.first <<
"'");
185 if (!identifier.empty()) {
187 <<
"' and '" << identifier_name
188 <<
"' are mutually exclusive");
190 identifier = element.second->stringValue();
191 identifier_name = element.first;
193 }
else if (element.first ==
"hostname") {
194 hostname = element.second->stringValue();
195 }
else if (element.first ==
"user-context") {
196 user_context = element.second;
201 if (identifier_name.empty()) {
205 std::ostringstream s;
207 if (s.tellp() != std::streampos(0)) {
213 " be specified for host reservation: "
219 host.reset(
new Host(identifier, identifier_name, SUBNET_ID_UNUSED,
220 SUBNET_ID_UNUSED,
IOAddress(
"0.0.0.0"), hostname));
224 host->setContext(user_context);
226 }
catch (
const std::exception& ex) {
229 << reservation_data->getPosition() <<
")");
248 bool encapsulate_options) {
250 encapsulate_options);
252 host->setIPv4SubnetID(subnet_id);
254 for (
auto const& element : reservation_data->mapValue()) {
258 if (element.first ==
"option-data") {
265 parser.
parse(cfg_option, element.second, encapsulate_options);
271 if (element.first ==
"ip-address") {
272 host->setIPv4Reservation(
IOAddress(element.second->
274 }
else if (element.first ==
"next-server") {
275 host->setNextServer(
IOAddress(element.second->stringValue()));
277 }
else if (element.first ==
"server-hostname") {
278 host->setServerHostname(element.second->stringValue());
280 }
else if (element.first ==
"boot-file-name") {
281 host->setBootFileName(element.second->stringValue());
283 }
else if (element.first ==
"client-classes") {
284 for (
auto const& class_element : element.second->listValue()) {
285 host->addClientClass4(class_element->stringValue());
289 }
catch (
const std::exception& ex) {
292 << element.second->getPosition() <<
")");
300const std::set<std::string>&
302 return (getSupportedParams4(identifiers_only));
308 bool encapsulate_options) {
310 encapsulate_options);
312 host->setIPv6SubnetID(subnet_id);
317 ConstElementPtr excluded_prefixes = reservation_data->get(
"excluded-prefixes");
318 ConstElementPtr client_classes = reservation_data->get(
"client-classes");
331 parser.
parse(cfg_option, option_data, encapsulate_options);
335 for (
size_t idx = 0; idx < ip_addresses->size(); ++idx) {
340 std::string addr = element->stringValue();
344 }
catch (
const std::exception& ex) {
347 << element->getPosition() <<
")");
352 if (excluded_prefixes) {
355 "requires the 'prefixes' parameter");
357 if (excluded_prefixes->size() != prefixes->size()) {
359 "does not match the 'prefixes' parameter: "
360 << excluded_prefixes->size() <<
" != "
361 << prefixes->size());
366 for (
size_t idx = 0; idx < prefixes->size(); ++idx) {
369 std::string prefix = element->stringValue();
371 uint8_t prefix_len(128);
372 parsePrefix(prefix, addr, prefix_len,
"prefix reservation");
374 std::string exclude(
"");
375 if (excluded_prefixes) {
376 element = excluded_prefixes->get(idx);
377 exclude = element->stringValue();
379 if (!exclude.empty()) {
381 uint8_t excluded_prefix_len(0);
382 parsePrefix(exclude, excluded_prefix, excluded_prefix_len,
386 res.setPDExclude(excluded_prefix, excluded_prefix_len);
388 host->addReservation(res);
389 }
catch (
const std::exception& ex) {
392 << element->getPosition() <<
")");
397 if (client_classes) {
399 for (
auto const& class_element : client_classes->listValue()) {
400 host->addClientClass6(class_element->stringValue());
402 }
catch (
const std::exception& ex) {
405 << client_classes->getPosition() <<
")");
412const std::set<std::string>&
414 return (getSupportedParams6(identifiers_only));
431 for (
auto const& element : ids_list->listValue()) {
432 std::string id_name = element->stringValue();
434 if (id_name !=
"auto") {
447 " no other values can be specified within '"
448 "host-reservation-identifiers' list");
453 for (
unsigned int i = 0;
456 std::string supported_id_name =
464 }
catch (
const std::exception& ex) {
467 << element->getPosition() <<
")");
474 " be empty (" << ids_list->getPosition() <<
")");
486 return (getSupportedParams4(
true).count(id_name) > 0);
496 return (getSupportedParams6(
true).count(id_name) > 0);
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
The IOAddress class represents an IP addresses (version agnostic)
static CfgMgr & instance()
returns a single instance of Configuration Manager
To be removed. Please use ConfigError instead.
HostReservationIdsParser4()
Constructor.
virtual bool isSupportedIdentifier(const std::string &id_name) const
Checks if specified identifier name is supported for DHCPv4.
HostReservationIdsParser6()
Constructor.
virtual bool isSupportedIdentifier(const std::string &id_name) const
Checks if specified identifier name is supported for DHCPv6.
Parser for a list of host identifiers.
CfgHostOperationsPtr staging_cfg_
Pointer to the object holding configuration.
virtual bool isSupportedIdentifier(const std::string &id_name) const =0
Checks if specified identifier name is supported in the context of the parser.
HostReservationIdsParser()
Constructor.
void parse(isc::data::ConstElementPtr ids_list)
Parses a list of host identifiers.
virtual void parseInternal(isc::data::ConstElementPtr ids_list)
Parses a list of host identifiers.
virtual const std::set< std::string > & getSupportedParameters(const bool identifiers_only) const
Returns set of the supported parameters for DHCPv4.
virtual HostPtr parseInternal(const SubnetID &subnet_id, isc::data::ConstElementPtr reservation_data, bool encapsulate_options)
Parses a single host reservation for DHCPv4.
virtual HostPtr parseInternal(const SubnetID &subnet_id, isc::data::ConstElementPtr reservation_data, bool encapsulate_options)
Parses a single host reservation for DHCPv6.
virtual const std::set< std::string > & getSupportedParameters(const bool identifiers_only) const
Returns set of the supported parameters for DHCPv6.
virtual HostPtr parse(const SubnetID &subnet_id, isc::data::ConstElementPtr reservation_data, bool encapsulate_options=true) final
Parses a single entry for host reservation.
virtual bool isIdentifierParameter(const std::string ¶m_name) const
Checks if the specified parameter is a host identifier.
virtual const std::set< std::string > & getSupportedParameters(const bool identifiers_only) const =0
Returns set of the supported parameters.
virtual HostPtr parseInternal(const SubnetID &subnet_id, isc::data::ConstElementPtr reservation_data, bool encapsulate_options)
Parses a single entry for host reservation.
virtual bool isSupportedParameter(const std::string ¶m_name) const
Checks if the specified parameter is supported by the parser.
Represents a device with IPv4 and/or IPv6 reservations.
IdentifierType
Type of the host identifier.
static const IdentifierType LAST_IDENTIFIER_TYPE
Constant pointing to the last identifier of the IdentifierType enumeration.
static std::string getIdentifierName(const IdentifierType &type)
Returns name of the identifier of a specified type.
IPv6 reservation for a host.
Parser for option data values within a subnet.
void parse(const CfgOptionPtr &cfg, isc::data::ConstElementPtr option_data_list, bool encapsulate=true)
Parses a list of options, instantiates them and stores in cfg.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
IOAddress firstAddrInPrefix(const IOAddress &prefix, uint8_t len)
This code is based on similar code from the Dibbler project.
boost::shared_ptr< const Element > ConstElementPtr
boost::shared_ptr< CfgOption > CfgOptionPtr
Non-const pointer.
boost::shared_ptr< Host > HostPtr
Pointer to the Host object.
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Defines the logger used by the top-level component of kea-lfc.