Kea  1.5.0
cfg_hosts.cc
Go to the documentation of this file.
1 // Copyright (C) 2014-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
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #include <config.h>
8 #include <dhcp/duid.h>
9 #include <dhcp/hwaddr.h>
10 #include <dhcpsrv/cfg_hosts.h>
11 #include <dhcpsrv/cfg_hosts_util.h>
12 #include <dhcpsrv/hosts_log.h>
13 #include <dhcpsrv/cfgmgr.h>
14 #include <exceptions/exceptions.h>
15 #include <util/encode/hex.h>
16 #include <ostream>
17 #include <string>
18 #include <vector>
19 
20 using namespace isc::asiolink;
21 using namespace isc::data;
22 
23 namespace isc {
24 namespace dhcp {
25 
27 CfgHosts::getAll(const Host::IdentifierType& identifier_type,
28  const uint8_t* identifier_begin,
29  const size_t identifier_len) const {
30  // Do not issue logging message here because it will be logged by
31  // the getAllInternal method.
32  ConstHostCollection collection;
33  getAllInternal<ConstHostCollection>(identifier_type, identifier_begin,
34  identifier_len, collection);
35  return (collection);
36 }
37 
39 CfgHosts::getAll(const Host::IdentifierType& identifier_type,
40  const uint8_t* identifier_begin, const size_t identifier_len) {
41  // Do not issue logging message here because it will be logged by
42  // the getAllInternal method.
43  HostCollection collection;
44  getAllInternal<HostCollection>(identifier_type, identifier_begin,
45  identifier_len, collection);
46  return (collection);
47 }
48 
50 CfgHosts::getAll4(const IOAddress& address) const {
51  // Do not issue logging message here because it will be logged by
52  // the getAllInternal4 method.
53  ConstHostCollection collection;
54  getAllInternal4<ConstHostCollection>(address, collection);
55  return (collection);
56 }
57 
59 CfgHosts::getAll4(const IOAddress& address) {
60  // Do not issue logging message here because it will be logged by
61  // the getAllInternal4 method.
62  HostCollection collection;
63  getAllInternal4<HostCollection>(address, collection);
64  return (collection);
65 }
66 
68 CfgHosts::getAll6(const IOAddress& address) const {
69  // Do not issue logging message here because it will be logged by
70  // the getAllInternal6 method.
71  ConstHostCollection collection;
72  getAllInternal6<ConstHostCollection>(address, collection);
73  return (collection);
74 }
75 
77 CfgHosts::getAll6(const IOAddress& address) {
78  // Do not issue logging message here because it will be logged by
79  // the getAllInternal6 method.
80  HostCollection collection;
81  getAllInternal6<HostCollection>(address, collection);
82  return (collection);
83 }
84 
85 template<typename Storage>
86 void
87 CfgHosts::getAllInternal(const Host::IdentifierType& identifier_type,
88  const uint8_t* identifier,
89  const size_t identifier_len,
90  Storage& storage) const {
91 
92  // Convert host identifier into textual format for logging purposes.
93  // This conversion is exception free.
94  std::string identifier_text = Host::getIdentifierAsText(identifier_type,
95  identifier,
96  identifier_len);
97  LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ALL_IDENTIFIER)
98  .arg(identifier_text);
99 
100  // Use the identifier and identifier type as a composite key.
101  const HostContainerIndex0& idx = hosts_.get<0>();
102  boost::tuple<const std::vector<uint8_t>, const Host::IdentifierType> t =
103  boost::make_tuple(std::vector<uint8_t>(identifier,
104  identifier + identifier_len),
105  identifier_type);
106 
107  // Append each Host object to the storage.
108  for (HostContainerIndex0::iterator host = idx.lower_bound(t);
109  host != idx.upper_bound(t);
110  ++host) {
112  HOSTS_CFG_GET_ALL_IDENTIFIER_HOST)
113  .arg(identifier_text)
114  .arg((*host)->toText());
115  storage.push_back(*host);
116  }
117 
118  // Log how many hosts have been found.
119  LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS, HOSTS_CFG_GET_ALL_IDENTIFIER_COUNT)
120  .arg(identifier_text)
121  .arg(storage.size());
122 }
123 
124 template<typename Storage>
125 void
126 CfgHosts::getAllInternal4(const IOAddress& address, Storage& storage) const {
127  LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ALL_ADDRESS4)
128  .arg(address.toText());
129 
130  // Must not specify address other than IPv4.
131  if (!address.isV4()) {
132  isc_throw(BadHostAddress, "must specify an IPv4 address when searching"
133  " for a host, specified address was " << address);
134  }
135  // Search for the Host using the reserved IPv4 address as a key.
136  const HostContainerIndex1& idx = hosts_.get<1>();
137  HostContainerIndex1Range r = idx.equal_range(address);
138  // Append each Host object to the storage.
139  for (HostContainerIndex1::iterator host = r.first; host != r.second;
140  ++host) {
142  HOSTS_CFG_GET_ALL_ADDRESS4_HOST)
143  .arg(address.toText())
144  .arg((*host)->toText());
145  storage.push_back(*host);
146  }
147 
148  LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS, HOSTS_CFG_GET_ALL_ADDRESS4_COUNT)
149  .arg(address.toText())
150  .arg(storage.size());
151 }
152 
153 template<typename Storage>
154 void
155 CfgHosts::getAllInternal6(const IOAddress& address, Storage& storage) const {
156  LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ALL_ADDRESS6)
157  .arg(address.toText());
158 
159  // Must not specify address other than IPv6.
160  if (!address.isV6()) {
161  isc_throw(BadHostAddress, "must specify an IPv6 address when searching"
162  " for a host, specified address was " << address);
163  }
164  // Search for the Host using the reserved IPv6 address as a key.
165  const HostContainerIndex1& idx = hosts_.get<1>();
166  HostContainerIndex1Range r = idx.equal_range(address);
167  // Append each Host object to the storage.
168  for (HostContainerIndex1::iterator host = r.first; host != r.second;
169  ++host) {
171  HOSTS_CFG_GET_ALL_ADDRESS6_HOST)
172  .arg(address.toText())
173  .arg((*host)->toText());
174  storage.push_back(*host);
175  }
176 
177  LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS, HOSTS_CFG_GET_ALL_ADDRESS6_COUNT)
178  .arg(address.toText())
179  .arg(storage.size());
180 }
181 
183 CfgHosts::get4(const SubnetID& subnet_id,
184  const Host::IdentifierType& identifier_type,
185  const uint8_t* identifier_begin,
186  const size_t identifier_len) const {
187  return (getHostInternal(subnet_id, false, identifier_type, identifier_begin,
188  identifier_len));
189 }
190 
191 HostPtr
192 CfgHosts::get4(const SubnetID& subnet_id,
193  const Host::IdentifierType& identifier_type,
194  const uint8_t* identifier_begin,
195  const size_t identifier_len) {
196  return (getHostInternal(subnet_id, false, identifier_type, identifier_begin,
197  identifier_len));
198 }
199 
201 CfgHosts::get4(const SubnetID& subnet_id, const IOAddress& address) const {
202  LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS4)
203  .arg(subnet_id).arg(address.toText());
204 
205  ConstHostCollection hosts = getAll4(address);
206  for (ConstHostCollection::const_iterator host = hosts.begin();
207  host != hosts.end(); ++host) {
208  if ((*host)->getIPv4SubnetID() == subnet_id) {
210  HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS4_HOST)
211  .arg(subnet_id)
212  .arg(address.toText())
213  .arg((*host)->toText());
214  return (*host);
215  }
216  }
217 
218  LOG_DEBUG(hosts_logger, HOSTS_DBG_RESULTS, HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS4_NULL)
219  .arg(subnet_id).arg(address.toText());
220  return (ConstHostPtr());
221 }
222 
223 
225 CfgHosts::get6(const SubnetID& subnet_id,
226  const Host::IdentifierType& identifier_type,
227  const uint8_t* identifier_begin,
228  const size_t identifier_len) const {
229  return (getHostInternal(subnet_id, true, identifier_type, identifier_begin,
230  identifier_len));
231 }
232 
233 HostPtr
234 CfgHosts::get6(const SubnetID& subnet_id,
235  const Host::IdentifierType& identifier_type,
236  const uint8_t* identifier_begin,
237  const size_t identifier_len) {
238  return (getHostInternal(subnet_id, true, identifier_type, identifier_begin,
239  identifier_len));
240 }
241 
243 CfgHosts::get6(const IOAddress& prefix, const uint8_t prefix_len) const {
244  return (getHostInternal6<ConstHostPtr>(prefix, prefix_len));
245 }
246 
247 HostPtr
248 CfgHosts::get6(const IOAddress& prefix, const uint8_t prefix_len) {
249  return (getHostInternal6<HostPtr>(prefix, prefix_len));
250 }
251 
253 CfgHosts::get6(const SubnetID& subnet_id,
254  const asiolink::IOAddress& address) const {
255  // Do not log here because getHostInternal6 logs.
256  return (getHostInternal6<ConstHostPtr, ConstHostCollection>(subnet_id, address));
257 }
258 
259 HostPtr
260 CfgHosts::get6(const SubnetID& subnet_id,
261  const asiolink::IOAddress& address) {
262  // Do not log here because getHostInternal6 logs.
263  return (getHostInternal6<HostPtr, HostCollection>(subnet_id, address));
264 }
265 
266 template<typename ReturnType, typename Storage>
267 ReturnType
268 CfgHosts::getHostInternal6(const SubnetID& subnet_id,
269  const asiolink::IOAddress& address) const {
270  LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS6)
271  .arg(subnet_id).arg(address.toText());
272 
273  Storage storage;
274  getAllInternal6<Storage>(subnet_id, address, storage);
275  switch (storage.size()) {
276  case 0:
278  HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS6_NULL)
279  .arg(subnet_id)
280  .arg(address.toText());
281  return (HostPtr());
282 
283  case 1:
285  HOSTS_CFG_GET_ONE_SUBNET_ID_ADDRESS6_HOST)
286  .arg(subnet_id)
287  .arg(address.toText())
288  .arg((*storage.begin())->toText());
289  return (*storage.begin());
290 
291  default:
292  isc_throw(DuplicateHost, "more than one reservation found"
293  " for the host belonging to the subnet with id '"
294  << subnet_id << "' and using the address '"
295  << address.toText() << "'");
296  }
297 
298 }
299 
300 template<typename ReturnType>
301 ReturnType
302 CfgHosts::getHostInternal6(const asiolink::IOAddress& prefix,
303  const uint8_t prefix_len) const {
304  LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ONE_PREFIX)
305  .arg(prefix.toText()).arg(static_cast<int>(prefix_len));
306 
307  // Let's get all reservations that match subnet_id, address.
308  const HostContainer6Index0& idx = hosts6_.get<0>();
309  HostContainer6Index0Range r = make_pair(idx.lower_bound(prefix),
310  idx.upper_bound(prefix));
311  for (HostContainer6Index0::iterator resrv = r.first; resrv != r.second;
312  ++resrv) {
313  if (resrv->resrv_.getPrefixLen() == prefix_len) {
315  HOSTS_CFG_GET_ONE_PREFIX_HOST)
316  .arg(prefix.toText())
317  .arg(static_cast<int>(prefix_len))
318  .arg(resrv->host_->toText());
319  return (resrv->host_);
320  }
321  }
322 
324  HOSTS_CFG_GET_ONE_PREFIX_NULL)
325  .arg(prefix.toText())
326  .arg(static_cast<int>(prefix_len));
327  return (ReturnType());
328 }
329 
330 template<typename Storage>
331 void
332 CfgHosts::getAllInternal6(const SubnetID& subnet_id,
333  const asiolink::IOAddress& address,
334  Storage& storage) const {
335  LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS6)
336  .arg(subnet_id).arg(address.toText());
337 
338  // Must not specify address other than IPv6.
339  if (!address.isV6()) {
340  isc_throw(BadHostAddress, "must specify an IPv6 address when searching"
341  " for a host, specified address was " << address);
342  }
343 
344  // Let's get all reservations that match subnet_id, address.
345  const HostContainer6Index1& idx = hosts6_.get<1>();
346  HostContainer6Index1Range r = make_pair(idx.lower_bound(boost::make_tuple(subnet_id, address)),
347  idx.upper_bound(boost::make_tuple(subnet_id, address)));
348 
349  // For each IPv6 reservation, add the host to the results list. Fortunately,
350  // in all sane cases, there will be only one such host. (Each host can have
351  // multiple addresses reserved, but for each (address, subnet_id) there should
352  // be at most one host reserving it).
353  for(HostContainer6Index1::iterator resrv = r.first; resrv != r.second; ++resrv) {
355  HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS6_HOST)
356  .arg(subnet_id)
357  .arg(address.toText())
358  .arg(resrv->host_->toText());
359  storage.push_back(resrv->host_);
360  }
361 
363  HOSTS_CFG_GET_ALL_SUBNET_ID_ADDRESS6_COUNT)
364  .arg(subnet_id)
365  .arg(address.toText())
366  .arg(storage.size());
367 }
368 
369 HostPtr
370 CfgHosts::getHostInternal(const SubnetID& subnet_id, const bool subnet6,
371  const Host::IdentifierType& identifier_type,
372  const uint8_t* identifier,
373  const size_t identifier_len) const {
374 
375  LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_GET_ONE_SUBNET_ID_IDENTIFIER)
376  .arg(subnet6 ? "IPv6" : "IPv4")
377  .arg(subnet_id)
378  .arg(Host::getIdentifierAsText(identifier_type, identifier, identifier_len));
379 
380  // Get all hosts for a specified identifier. This may return multiple hosts
381  // for different subnets, but the number of hosts returned should be low
382  // because one host presumably doesn't show up in many subnets.
383  HostCollection hosts;
384  getAllInternal<HostCollection>(identifier_type, identifier, identifier_len,
385  hosts);
386 
387  HostPtr host;
388  // Iterate over the returned hosts and select those for which the
389  // subnet id matches.
390  for (HostCollection::const_iterator host_it = hosts.begin();
391  host_it != hosts.end(); ++host_it) {
392  // Check if this is IPv4 subnet or IPv6 subnet.
393  SubnetID host_subnet_id = subnet6 ? (*host_it)->getIPv6SubnetID() :
394  (*host_it)->getIPv4SubnetID();
395 
396  if (subnet_id == host_subnet_id) {
397  // If this is the first occurrence of the host for this subnet,
398  // remember it. But, if we find that this is second @c Host object
399  // for the same client, it is a misconfiguration. Most likely,
400  // the administrator has specified one reservation for a HW
401  // address and another one for the DUID, which gives an ambiguous
402  // result, and we don't know which reservation we should choose.
403  // Therefore, throw an exception.
404  if (!host) {
405  host = *host_it;
406 
407  } else {
408  isc_throw(DuplicateHost, "more than one reservation found"
409  " for the host belonging to the subnet with id '"
410  << subnet_id << "' and using the identifier '"
411  << Host::getIdentifierAsText(identifier_type,
412  identifier,
413  identifier_len)
414  << "'");
415  }
416  }
417  }
418 
419  if (host) {
421  HOSTS_CFG_GET_ONE_SUBNET_ID_IDENTIFIER_HOST)
422  .arg(subnet_id)
423  .arg(Host::getIdentifierAsText(identifier_type, identifier,
424  identifier_len))
425  .arg(host->toText());
426 
427  } else {
429  HOSTS_CFG_GET_ONE_SUBNET_ID_IDENTIFIER_NULL)
430  .arg(subnet_id)
431  .arg(Host::getIdentifierAsText(identifier_type, identifier,
432  identifier_len));
433  }
434 
435  return (host);
436 }
437 
438 void
439 CfgHosts::add(const HostPtr& host) {
440  LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_ADD_HOST)
441  .arg(host ? host->toText() : "(no-host)");
442 
443  // Sanity check that the host is non-null.
444  if (!host) {
445  isc_throw(BadValue, "specified host object must not be NULL when it"
446  " is added to the configuration");
447  }
448 
449  // At least one subnet ID must be used
450  if (host->getIPv4SubnetID() == SUBNET_ID_UNUSED &&
451  host->getIPv6SubnetID() == SUBNET_ID_UNUSED) {
452  isc_throw(BadValue, "must not use both IPv4 and IPv6 subnet ids of"
453  " 0 when adding new host reservation");
454  }
455 
456  add4(host);
457 
458  add6(host);
459 }
460 
461 void
462 CfgHosts::add4(const HostPtr& host) {
463 
464  HWAddrPtr hwaddr = host->getHWAddress();
465  DuidPtr duid = host->getDuid();
466 
467  // There should be at least one resource reserved: hostname, IPv4
468  // address, siaddr, sname, file or IPv6 address or prefix.
470  if (host->getHostname().empty() &&
471  (host->getIPv4Reservation().isV4Zero()) &&
472  !host->hasIPv6Reservation() &&
473  host->getNextServer().isV4Zero() &&
474  host->getServerHostname().empty() &&
475  host->getBootFileName().empty() &&
476  host->getCfgOption4()->empty() &&
477  host->getCfgOption6()->empty() &&
478  host->getClientClasses4().empty() &&
479  host->getClientClasses6().empty()) {
480  std::ostringstream s;
481  if (hwaddr) {
482  s << "for DUID: " << hwaddr->toText();
483  } else if (duid) {
484  s << "for HW address: " << duid->toText();
485  }
486  isc_throw(BadValue, "specified reservation " << s.str()
487  << " must include at least one resource, i.e. "
488  "hostname, IPv4 address, IPv6 address/prefix, "
489  "options");
490  }
491 
492  // Check for duplicates for the specified IPv4 subnet.
493  if (host->getIPv4SubnetID() != SUBNET_ID_UNUSED) {
494  if (hwaddr && !hwaddr->hwaddr_.empty() &&
495  get4(host->getIPv4SubnetID(), Host::IDENT_HWADDR,
496  &hwaddr->hwaddr_[0], hwaddr->hwaddr_.size())) {
497  isc_throw(DuplicateHost, "failed to add new host using the HW"
498  << " address '" << hwaddr->toText(false)
499  << "' to the IPv4 subnet id '" << host->getIPv4SubnetID()
500  << "' as this host has already been added");
501  }
502  if (duid && !duid->getDuid().empty() &&
503  get4(host->getIPv4SubnetID(), Host::IDENT_DUID,
504  &duid->getDuid()[0], duid->getDuid().size())) {
505  isc_throw(DuplicateHost, "failed to add new host using the "
506  << "DUID '" << duid->toText()
507  << "' to the IPv4 subnet id '" << host->getIPv4SubnetID()
508  << "' as this host has already been added");
509  }
510  // Check for duplicates for the specified IPv6 subnet.
511  } else if (host->getIPv6SubnetID() != SUBNET_ID_UNUSED) {
512  if (duid && !duid->getDuid().empty() &&
513  get6(host->getIPv6SubnetID(), Host::IDENT_DUID,
514  &duid->getDuid()[0], duid->getDuid().size())) {
515  isc_throw(DuplicateHost, "failed to add new host using the "
516  << "DUID '" << duid->toText()
517  << "' to the IPv6 subnet id '" << host->getIPv6SubnetID()
518  << "' as this host has already been added");
519  }
520  if (hwaddr && !hwaddr->hwaddr_.empty() &&
521  get6(host->getIPv6SubnetID(), Host::IDENT_HWADDR,
522  &hwaddr->hwaddr_[0], hwaddr->hwaddr_.size())) {
523  isc_throw(DuplicateHost, "failed to add new host using the HW"
524  << " address '" << hwaddr->toText(false)
525  << "' to the IPv6 subnet id '" << host->getIPv6SubnetID()
526  << "' as this host has already been added");
527  }
528  }
529 
530  // Check if the address is already reserved for the specified IPv4 subnet.
531  if (!host->getIPv4Reservation().isV4Zero() &&
532  (host->getIPv4SubnetID() != SUBNET_ID_UNUSED) &&
533  get4(host->getIPv4SubnetID(), host->getIPv4Reservation())) {
534  isc_throw(ReservedAddress, "failed to add new host using the HW"
535  " address '" << (hwaddr ? hwaddr->toText(false) : "(null)")
536  << " and DUID '" << (duid ? duid->toText() : "(null)")
537  << "' to the IPv4 subnet id '" << host->getIPv4SubnetID()
538  << "' for the address " << host->getIPv4Reservation()
539  << ": There's already a reservation for this address");
540  }
541 
542  // Check if the (identifier type, identifier) tuple is already used.
543  const std::vector<uint8_t>& id = host->getIdentifier();
544  if ((host->getIPv4SubnetID() != SUBNET_ID_UNUSED) && !id.empty()) {
545  if (get4(host->getIPv4SubnetID(), host->getIdentifierType(), &id[0],
546  id.size())) {
547  isc_throw(DuplicateHost, "failed to add duplicate IPv4 host using identifier: "
548  << Host::getIdentifierAsText(host->getIdentifierType(),
549  &id[0], id.size()));
550  }
551  }
552 
553  // This is a new instance - add it.
554  hosts_.insert(host);
555 }
556 
557 void
558 CfgHosts::add6(const HostPtr& host) {
559 
560  if (host->getIPv6SubnetID() == SUBNET_ID_UNUSED) {
561  // This is IPv4-only host. No need to add it to v6 tables.
562  return;
563  }
564 
565  HWAddrPtr hwaddr = host->getHWAddress();
566  DuidPtr duid = host->getDuid();
567 
568  // Get all reservations for this host.
569  IPv6ResrvRange reservations = host->getIPv6Reservations();
570 
571  // Check if there are any IPv6 reservations.
572  if (std::distance(reservations.first, reservations.second) == 0) {
573  // If there aren't, we don't need to add this to hosts6_, which is used
574  // for getting hosts by their IPv6 address reservations.
575  return;
576  }
577 
578  // Now for each reservation, insert corresponding (address, host) tuple.
579  for (IPv6ResrvIterator it = reservations.first; it != reservations.second;
580  ++it) {
581 
582  // If there's an entry for this (subnet-id, address), reject it.
583  if (get6(host->getIPv6SubnetID(), it->second.getPrefix())) {
584  isc_throw(DuplicateHost, "failed to add address reservation for "
585  << "host using the HW address '"
586  << (hwaddr ? hwaddr->toText(false) : "(null)")
587  << " and DUID '" << (duid ? duid->toText() : "(null)")
588  << "' to the IPv6 subnet id '" << host->getIPv6SubnetID()
589  << "' for address/prefix " << it->second.getPrefix()
590  << ": There's already reservation for this address/prefix");
591  }
592  hosts6_.insert(HostResrv6Tuple(it->second, host));
593  }
594 }
595 
596 bool
597 CfgHosts::del(const SubnetID& /*subnet_id*/, const asiolink::IOAddress& /*addr*/) {
599  isc_throw(NotImplemented, "sorry, not implemented");
600  return (false);
601 }
602 
603 size_t
604 CfgHosts::delAll4(const SubnetID& subnet_id) {
605  HostContainerIndex2& idx = hosts_.get<2>();
606  size_t erased = idx.erase(subnet_id);
607 
608  LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_DEL_ALL_SUBNET4)
609  .arg(erased)
610  .arg(subnet_id);
611 
612  return (erased);
613 }
614 
615 bool
616 CfgHosts::del4(const SubnetID& /*subnet_id*/,
617  const Host::IdentifierType& /*identifier_type*/,
618  const uint8_t* /*identifier_begin*/,
619  const size_t /*identifier_len*/) {
621  isc_throw(NotImplemented, "sorry, not implemented");
622  return (false);
623 }
624 
625 size_t
626 CfgHosts::delAll6(const SubnetID& subnet_id) {
627  // Delete IPv6 reservations.
628  HostContainer6Index2& idx6 = hosts6_.get<2>();
629  size_t erased_addresses = idx6.erase(subnet_id);
630 
631  // Delete hosts.
632  HostContainerIndex3& idx = hosts_.get<3>();
633  size_t erased_hosts = idx.erase(subnet_id);
634 
635  LOG_DEBUG(hosts_logger, HOSTS_DBG_TRACE, HOSTS_CFG_DEL_ALL_SUBNET6)
636  .arg(erased_hosts)
637  .arg(erased_addresses)
638  .arg(subnet_id);
639 
640  return (erased_hosts);
641 }
642 
643 bool
644 CfgHosts::del6(const SubnetID& /*subnet_id*/,
645  const Host::IdentifierType& /*identifier_type*/,
646  const uint8_t* /*identifier_begin*/,
647  const size_t /*identifier_len*/) {
649  isc_throw(NotImplemented, "sorry, not implemented");
650  return (false);
651 }
652 
654 CfgHosts::toElement() const {
655  uint16_t family = CfgMgr::instance().getFamily();
656  if (family == AF_INET) {
657  return (toElement4());
658  } else if (family == AF_INET6) {
659  return (toElement6());
660  } else {
661  isc_throw(ToElementError, "CfgHosts::toElement: unknown "
662  "address family: " << family);
663  }
664 }
665 
667 CfgHosts::toElement4() const {
668  CfgHostsList result;
669  // Iterate using arbitrary the index 0
670  const HostContainerIndex0& idx = hosts_.get<0>();
671  for (HostContainerIndex0::const_iterator host = idx.begin();
672  host != idx.end(); ++host) {
673 
674  // Convert host to element representation
675  ElementPtr map = (*host)->toElement4();
676 
677  // Push it on the list
678  SubnetID subnet_id = (*host)->getIPv4SubnetID();
679  result.add(subnet_id, map);
680  }
681  return (result.externalize());
682 }
683 
685 CfgHosts::toElement6() const {
686  CfgHostsList result;
687  // Iterate using arbitrary the index 0
688  const HostContainerIndex0& idx = hosts_.get<0>();
689  for (HostContainerIndex0::const_iterator host = idx.begin();
690  host != idx.end(); ++host) {
691 
692  // Convert host to Element representation
693  ElementPtr map = (*host)->toElement6();
694 
695  // Push it on the list
696  SubnetID subnet_id = (*host)->getIPv6SubnetID();
697  result.add(subnet_id, map);
698  }
699  return (result.externalize());
700 }
701 
702 } // end of namespace isc::dhcp
703 } // end of namespace isc
isc::dhcp::hosts_logger
isc::log::Logger hosts_logger("hosts")
Logger for the HostMgr and the code it calls.
Definition: hosts_log.h:51
cfg_hosts.h
isc::dhcp::CfgHostsList::externalize
isc::data::ElementPtr externalize() const
Externalize the map to a list Element.
Definition: cfg_hosts_util.cc:63
hosts_log.h
isc::dhcp::Host::IdentifierType
IdentifierType
Type of the host identifier.
Definition: host.h:252
isc::dhcp::HostContainerIndex3
HostContainer::nth_index< 3 >::type HostContainerIndex3
Forth index type in the HostContainer.
Definition: host_container.h:122
isc::dhcp::DuplicateHost
Exception thrown when the duplicate Host object is detected.
Definition: base_host_data_source.h:21
isc::dhcp::HostContainerIndex0
HostContainer::nth_index< 0 >::type HostContainerIndex0
First index type in the HostContainer.
Definition: host_container.h:92
duid.h
isc::dhcp::DuidPtr
boost::shared_ptr< DUID > DuidPtr
Definition: duid.h:20
isc::dhcp::HostContainer6Index1
HostContainer6::nth_index< 1 >::type HostContainer6Index1
Second index type in the HostContainer6.
Definition: host_container.h:229
isc::dhcp::HostPtr
boost::shared_ptr< Host > HostPtr
Pointer to the Host object.
Definition: host.h:725
isc::data
Definition: cfg_to_element.h:25
isc::dhcp::HostContainer6Index0Range
std::pair< HostContainer6Index0::iterator, HostContainer6Index0::iterator > HostContainer6Index0Range
Results range returned using the HostContainer6Index0.
Definition: host_container.h:223
isc::dhcp::HOSTS_DBG_TRACE_DETAIL_DATA
const int HOSTS_DBG_TRACE_DETAIL_DATA
Records detailed results of lookups.
Definition: hosts_log.h:43
isc::dhcp::HostContainer6Index1Range
std::pair< HostContainer6Index1::iterator, HostContainer6Index1::iterator > HostContainer6Index1Range
Results range returned using the HostContainer6Index1.
Definition: host_container.h:233
isc
Defines the logger used by the top-level component of kea-dhcp-ddns.
Definition: agent_parser.cc:144
isc::dhcp::HWAddrPtr
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
Definition: hwaddr.h:154
hex.h
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition: exceptions/exceptions.h:192
LOG_DEBUG
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition: macros.h:14
isc::BadValue
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
Definition: exceptions/exceptions.h:132
isc::dhcp::HostContainerIndex1Range
std::pair< HostContainerIndex1::iterator, HostContainerIndex1::iterator > HostContainerIndex1Range
Results range returned using the HostContainerIndex1.
Definition: host_container.h:106
isc::ToElementError
Cannot unparse error.
Definition: cfg_to_element.h:19
isc::dhcp::CfgHostsList::add
void add(SubnetID id, isc::data::ElementPtr resv)
Add a host reservation to the map.
Definition: cfg_hosts_util.cc:75
isc::dhcp::HOSTS_DBG_RESULTS
const int HOSTS_DBG_RESULTS
Records the results of the lookups.
Definition: hosts_log.h:33
hwaddr.h
cfgmgr.h
isc::dhcp::HOSTS_DBG_TRACE
const int HOSTS_DBG_TRACE
Logging levels for the host reservations management.
Definition: hosts_log.h:27
isc::dhcp::CfgHostsList
Utility class to represent host reservation configurations internally as a map keyed by subnet IDs,...
Definition: cfg_hosts_util.h:18
isc::dhcp::HostContainer6Index0
HostContainer6::nth_index< 0 >::type HostContainer6Index0
First index type in the HostContainer6.
Definition: host_container.h:219
cfg_hosts_util.h
isc::dhcp::CfgHostsList::get
isc::data::ConstElementPtr get(SubnetID id) const
Return the host reservations for a subnet ID.
Definition: cfg_hosts_util.cc:86
isc::dhcp::ConstHostCollection
std::vector< ConstHostPtr > ConstHostCollection
Collection of the const Host objects.
Definition: host.h:731
exceptions.h
isc::dhcp::ConstHostPtr
boost::shared_ptr< const Host > ConstHostPtr
Const pointer to the Host object.
Definition: host.h:728
isc::dhcp::HostContainerIndex1
HostContainer::nth_index< 1 >::type HostContainerIndex1
Second index type in the HostContainer.
Definition: host_container.h:102
isc::data::ElementPtr
boost::shared_ptr< Element > ElementPtr
Definition: data.h:20
isc::NotImplemented
A generic exception that is thrown when a function is not implemented.
Definition: exceptions/exceptions.h:165
isc::dhcp::SubnetID
uint32_t SubnetID
Unique identifier for a subnet (both v4 and v6)
Definition: lease.h:24
isc::dhcp::IPv6ResrvIterator
IPv6ResrvCollection::const_iterator IPv6ResrvIterator
Definition: host.h:186
isc::dhcp::HostContainer6Index2
HostContainer6::nth_index< 2 >::type HostContainer6Index2
Third index type in the HostContainer6.
Definition: host_container.h:239
isc::dhcp::HostContainerIndex2
HostContainer::nth_index< 2 >::type HostContainerIndex2
Third index type in the HostContainer.
Definition: host_container.h:112
isc::dhcp::IPv6ResrvRange
std::pair< IPv6ResrvIterator, IPv6ResrvIterator > IPv6ResrvRange
Definition: host.h:188
isc::dhcp::HostCollection
std::vector< HostPtr > HostCollection
Collection of the Host objects.
Definition: host.h:734