12 #include <boost/foreach.hpp>
13 #include <boost/lexical_cast.hpp>
15 #include <sys/socket.h>
32 const std::set<std::string>&
33 getSupportedParams4(
const bool identifiers_only =
false) {
35 static std::set<std::string> identifiers_set;
37 static std::set<std::string> params_set;
40 if (identifiers_set.empty()) {
41 identifiers_set.insert(
"hw-address");
42 identifiers_set.insert(
"duid");
43 identifiers_set.insert(
"circuit-id");
44 identifiers_set.insert(
"client-id");
45 identifiers_set.insert(
"flex-id");
48 if (params_set.empty()) {
49 params_set = identifiers_set;
50 params_set.insert(
"hostname");
51 params_set.insert(
"ip-address");
52 params_set.insert(
"option-data");
53 params_set.insert(
"next-server");
54 params_set.insert(
"server-hostname");
55 params_set.insert(
"boot-file-name");
56 params_set.insert(
"client-classes");
57 params_set.insert(
"user-context");
59 return (identifiers_only ? identifiers_set : params_set);
70 const std::set<std::string>&
71 getSupportedParams6(
const bool identifiers_only =
false) {
73 static std::set<std::string> identifiers_set;
75 static std::set<std::string> params_set;
78 if (identifiers_set.empty()) {
79 identifiers_set.insert(
"hw-address");
80 identifiers_set.insert(
"duid");
81 identifiers_set.insert(
"flex-id");
84 if (params_set.empty()) {
85 params_set = identifiers_set;
86 params_set.insert(
"hostname");
87 params_set.insert(
"ip-addresses");
88 params_set.insert(
"prefixes");
89 params_set.insert(
"option-data");
90 params_set.insert(
"client-classes");
91 params_set.insert(
"user-context");
93 return (identifiers_only ? identifiers_set : params_set);
102 HostReservationParser::parse(
const SubnetID& subnet_id,
104 return (parseInternal(subnet_id, reservation_data));
108 HostReservationParser::parseInternal(
const SubnetID&,
110 std::string identifier;
111 std::string identifier_name;
112 std::string hostname;
119 BOOST_FOREACH(
auto element, reservation_data->mapValue()) {
121 if (!isSupportedParameter(element.first)) {
123 " parameter '" << element.first <<
"'");
126 if (isIdentifierParameter(element.first)) {
127 if (!identifier.empty()) {
129 <<
"' and '" << identifier_name
130 <<
"' are mutually exclusive");
132 identifier = element.second->stringValue();
133 identifier_name = element.first;
135 }
else if (element.first ==
"hostname") {
136 hostname = element.second->stringValue();
137 }
else if (element.first ==
"user-context") {
138 user_context = element.second;
143 if (identifier_name.empty()) {
147 std::ostringstream s;
148 BOOST_FOREACH(std::string param_name, getSupportedParameters(
true)) {
149 if (s.tellp() != std::streampos(0)) {
155 " be specified for host reservation: "
161 host.reset(
new Host(identifier, identifier_name, SUBNET_ID_UNUSED,
162 SUBNET_ID_UNUSED,
IOAddress(
"0.0.0.0"), hostname));
166 host->setContext(user_context);
168 }
catch (
const std::exception& ex) {
171 << reservation_data->getPosition() <<
")");
178 HostReservationParser::isIdentifierParameter(
const std::string& param_name)
const {
179 return (getSupportedParameters(
true).count(param_name) > 0);
183 HostReservationParser::isSupportedParameter(
const std::string& param_name)
const {
184 return (getSupportedParameters(
false).count(param_name) > 0);
188 HostReservationParser4::parseInternal(
const SubnetID& subnet_id,
190 HostPtr host = HostReservationParser::parseInternal(subnet_id, reservation_data);
192 host->setIPv4SubnetID(subnet_id);
194 BOOST_FOREACH(
auto element, reservation_data->mapValue()) {
198 if (element.first ==
"option-data") {
205 parser.
parse(cfg_option, element.second);
211 if (element.first ==
"ip-address") {
212 host->setIPv4Reservation(
IOAddress(element.second->
214 }
else if (element.first ==
"next-server") {
215 host->setNextServer(
IOAddress(element.second->stringValue()));
217 }
else if (element.first ==
"server-hostname") {
218 host->setServerHostname(element.second->stringValue());
220 }
else if (element.first ==
"boot-file-name") {
221 host->setBootFileName(element.second->stringValue());
223 }
else if (element.first ==
"client-classes") {
225 element.second->listValue()) {
226 host->addClientClass4(class_element->stringValue());
230 }
catch (
const std::exception& ex) {
233 << element.second->getPosition() <<
")");
241 const std::set<std::string>&
242 HostReservationParser4::getSupportedParameters(
const bool identifiers_only)
const {
243 return (getSupportedParams4(identifiers_only));
247 HostReservationParser6::parseInternal(
const SubnetID& subnet_id,
249 HostPtr host = HostReservationParser::parseInternal(subnet_id, reservation_data);
251 host->setIPv6SubnetID(subnet_id);
253 BOOST_FOREACH(
auto element, reservation_data->mapValue()) {
258 if (element.first ==
"option-data") {
265 parser.
parse(cfg_option, element.second);
267 }
else if (element.first ==
"ip-addresses" || element.first ==
"prefixes") {
269 element.second->listValue()) {
274 std::string prefix = prefix_element->stringValue();
275 uint8_t prefix_len = 128;
280 if (element.first ==
"prefixes") {
283 size_t len_pos = prefix.find(
'/');
284 if (len_pos == std::string::npos) {
286 " requires prefix length be specified"
287 " in '" << prefix <<
"'");
291 }
else if (len_pos >= prefix.length() - 1) {
293 <<
"' requires length after '/'");
302 prefix_len = boost::lexical_cast<
303 unsigned int>(prefix.substr(len_pos + 1));
305 }
catch (
const boost::bad_lexical_cast&) {
307 << prefix.substr(len_pos + 1)
313 prefix.erase(len_pos);
316 resrv_type = IPv6Resrv::TYPE_PD;
320 host->addReservation(
IPv6Resrv(resrv_type,
324 }
catch (
const std::exception& ex) {
327 << prefix_element->getPosition() <<
")");
332 }
else if (element.first ==
"client-classes") {
335 element.second->listValue()) {
336 host->addClientClass6(class_element->stringValue());
338 }
catch (
const std::exception& ex) {
341 << element.second->getPosition() <<
")");
349 const std::set<std::string>&
350 HostReservationParser6::getSupportedParameters(
const bool identifiers_only)
const {
351 return (getSupportedParams6(identifiers_only));
354 HostReservationIdsParser::HostReservationIdsParser()
369 std::string id_name = element->stringValue();
371 if (id_name !=
"auto") {
384 " no other values can be specified within '"
385 "host-reservation-identifiers' list");
390 for (
unsigned int i = 0;
393 std::string supported_id_name =
401 }
catch (
const std::exception& ex) {
404 << element->getPosition() <<
")");
411 " be empty (" << ids_list->getPosition() <<
")");
423 return (getSupportedParams4(
true).count(id_name) > 0);
433 return (getSupportedParams6(
true).count(id_name) > 0);